Как условно обернуть div вокруг ng-контента

в зависимости от значения (логической) переменной класса я хотел бы, чтобы мой ng-content был либо обернут в div, либо не был обернут в div (т.е. div даже не должен быть в DOM)... Каков наилучший способ идти об этом? У меня есть Plunker, который пытается сделать это наиболее очевидным способом, используя ngIf . ... но это не работает... Он отображает содержимое только для одного из логических значений, но не для другого

Пожалуйста, помогите Спасибо!

http://plnkr.co/edit/omqLK0mKUIzqkkR3lQh8

@Component({
  selector: 'my-component',
  template: `

   <div *ngIf="insideRedDiv" style="display: inline; border: 1px red solid">
      <ng-content *ngIf="insideRedDiv"  ></ng-content> 
   </div>

   <ng-content *ngIf="!insideRedDiv"></ng-content>     

  `,
})
export class MyComponent {
  insideRedDiv: boolean = true;
}


@Component({
  template: `
    <my-component> ... "Here is the Content"  ... </my-component>
  `
})
export class App {}

person Somo S.    schedule 11.01.2017    source источник
comment
Хороший plunkr, хороший вопрос .. Возился с этим и тоже не могу понять. интересно было бы узнать решение   -  person jhhoff02    schedule 11.01.2017


Ответы (3)


Угловой ^4

В качестве обходного пути я могу предложить вам следующее решение:

<div *ngIf="insideRedDiv; else elseTpl" style="display: inline; border: 1px red solid">
  <ng-container *ngTemplateOutlet="elseTpl"></ng-container>
</div>

<ng-template #elseTpl><ng-content></ng-content> </ng-template>

Пример плунжера angular v4

Угловой ‹ 4

Здесь вы можете создать специальную директиву, которая будет делать то же самое:

<div *ngIf4="insideRedDiv; else elseTpl" style="display: inline; border: 1px red solid">
   <ng-container *ngTemplateOutlet="elseTpl"></ng-container>
</div>

<template #elseTpl><ng-content></ng-content></template>

Пример планкера

ngIf4.ts

class NgIfContext { public $implicit: any = null; }

@Directive({ selector: '[ngIf4]' })
export class NgIf4 {
  private context: NgIfContext = new NgIfContext();
  private elseTemplateRef: TemplateRef<NgIfContext>;
  private elseViewRef: EmbeddedViewRef<NgIfContext>;
  private viewRef: EmbeddedViewRef<NgIfContext>;

  constructor(private viewContainer: ViewContainerRef, private templateRef: TemplateRef<NgIfContext>) { }

  @Input()
  set ngIf4(condition: any) {
    this.context.$implicit = condition;
    this._updateView();
  }

  @Input()
  set ngIf4Else(templateRef: TemplateRef<NgIfContext>) {
    this.elseTemplateRef = templateRef;
    this.elseViewRef = null;
    this._updateView();
  }

  private _updateView() {
    if (this.context.$implicit) {
      this.viewContainer.clear();
      this.elseViewRef = null;

      if (this.templateRef) {
        this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef, this.context);
      }
    } else {
      if (this.elseViewRef) return;

      this.viewContainer.clear();
      this.viewRef = null;

      if (this.elseTemplateRef) {
        this.elseViewRef = this.viewContainer.createEmbeddedView(this.elseTemplateRef, this.context);
      }
    }
  }
}
person yurzui    schedule 18.01.2017
comment
Хотел бы я проголосовать за это дважды. Потратил вечность, пытаясь понять, как использовать ng-контент внутри * ngIf - person vangorra; 16.02.2017
comment
Спасибо, Юрзи, я долго пытался сформулировать этот лучший образец для поиска в Google. Angular 5 с этим справляется. - person user1059939; 22.02.2018
comment
Работает отлично! Довольно безумно кстати. Только что освоил Angular, но постоянно поражаюсь его мощи. - person Leaky; 19.07.2019
comment
Это круто, я боялся, что мне придется писать много повторяющегося кода. - person devqon; 28.04.2020

Помните, что всю эту логику можно вынести в отдельный компонент! (на основе ответа Юрзуи):

import { Component, Input } from '@angular/core';

@Component({
    selector: 'div-wrapper',
    template: `
    <div *ngIf="wrap; else unwrapped">
      <ng-content *ngTemplateOutlet="unwrapped">
      </ng-content>
    </div>
    <ng-template #unwrapped>
      <ng-content>
      </ng-content>
    </ng-template>
    `,
})
export class ConditionalDivComponent {
  @Input()
  public wrap = false;
}

Затем вы можете использовать его следующим образом:

<div-wrapper [wrap]="'true'">
 Hello world!        
</div-wrapper>
person charlie_pl    schedule 23.05.2017
comment
Мне больше нравится этот ответ. Другие ответы имеют слишком большую сложность html - person Max; 12.07.2018

Я проверил это и нашел открытую проблему на тему множественных включений с тегом. Это предотвращает определение нескольких тегов в одном файле шаблона.

Это объясняет, почему содержимое отображается правильно только тогда, когда в вашем примере с плункером удален другой тег.

Вы можете увидеть открытую проблему здесь: https://github.com/angular/angular/issues/ 7795

person Jolmari    schedule 11.01.2017
comment
Я полагаю, что, поскольку ngIf являются взаимоисключающими, два ng-контента никогда не отображаются одновременно, поэтому они не будут конфликтовать ... другая особенная вещь заключается в том, что это не происходит громко ИЛИ тихо, пока нет никакой ошибки. это явно не работает, как можно подумать.. Спасибо за проблему, я буду внимательно следить за ней! - person Somo S.; 11.01.2017