【问题标题】:How to conditionally wrap a div around ng-content如何有条件地将 div 包裹在 ng-content 周围
【发布时间】:2017-05-26 10:14:30
【问题描述】:

取决于(布尔)类变量的值,我希望我的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 {}

【问题讨论】:

  • 好plunkr,好问题..搞砸了,也想不通。我很想知道解决方案

标签: angular angular-ng-if angular2-ngcontent


【解决方案1】:

角度 ^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>

Plunker Example angular v4

角度

在这里你可以创建专门的指令来做同样的事情:

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

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

Plunker Example

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);
      }
    }
  }
}

【讨论】:

  • 希望我能投票两次。花了很长时间试图弄清楚如何在 *ngIf 中使用 ng-content
  • 谢谢 Yurzi,我花了很长时间尝试为 google 搜索配上这个顶级样本。 Angular 5 很好。
  • 效果很好!顺便说一句,相当疯狂。刚接触 Angular,但我一直对它的强大感到惊讶。
  • 这太棒了,我怕我不得不写很多重复的代码
【解决方案2】:

请记住,您可以将所有这些逻辑放在单独的组件中! (基于 yurzui 的回答):

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>

【讨论】:

  • 我更喜欢这个答案。其他答案的 html 复杂性太高
【解决方案3】:

我对此进行了检查,并发现了一个关于标签的多个嵌入主题的未解决问题。这可以防止您在单个模板文件中定义多个标签。

这解释了为什么只有在您的 plunker 示例中删除其他标签时才能正确显示内容。

您可以在此处查看未解决的问题: https://github.com/angular/angular/issues/7795

【讨论】:

  • 我认为由于 ngIf 是互斥的,因此两个“ng-contents”永远不会同时出现在视图中,因此它们不会“冲突”......另一个特别的事情是这不是大声或轻声失败,没有任何错误,但它显然没有像人们想象的那样工作。谢谢你的问题,我会密切关注它!
猜你喜欢
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 2014-05-28
相关资源
最近更新 更多