使用ng-content时如何消除内部组件

时间:2017-10-12 01:02:04

标签: angular angular2-ngcontent

我试图将弹出式菜单分解出来,以便我可以这样写:

<panel-menu>
  <panel-menu-item>Edit input</panel-menu-item>
  <panel-menu-item>Edit mappings</panel-menu-item>
  <panel-menu-item divider-before>Show agent code</panel-menu-item>
</panel-menu>

我有一个包含此HTML的panel-menu组件:

<div class="btn-group" [class.open]="...">
  <button type="button" class="btn btn-default" (click)="..."><i class="ion-gear-b icon-lg"></i></button>
  <ul class="dropdown-menu dropdown-menu-right">
    <ng-content select="panel-menu-item"></ng-content>
  </ul>
</div>
使用此HTML

panel-menu-item

<li *ngIf="dividerBefore" class="divider"></li>
<li><a><ng-content></ng-content></a></li>

问题是生成的DOM在panel-menu-itemul之间有一个li,这会破坏第三方CSS。

是否有某种方法只展示所选儿童的内容,而不是儿童本身?

This answer建议在li而不是组件上使用属性,但这会泄漏实现。 panel-menu的用户不应该知道实现了哪些元素菜单项。

1 个答案:

答案 0 :(得分:3)

要投射内容,您应该将内容包装在嵌入式视图中,如:

<强>面板菜单item.component.ts

@Component({
  selector: 'panel-menu-item',
  template: `
    <ng-template>
      <li *ngIf="dividerBefore" class="divider"></li>
      <li><a><ng-content></ng-content></a></li>
    </ng-template>
  `
})
export class PanelMenuItemComponent {
  @ViewChild(TemplateRef) content: TemplateRef<any>;
}

在前面的代码中,我将模板包装在ng-template标记中,并使用TemplateRef装饰器从中获取@ViewChild实例。

拥有TemplateRef,我们可以轻松管理模板的插入位置:

<强>面板menu.component.ts

@Component({
  selector: 'panel-menu',
  template: `
    <div class="btn-group" >
      <button type="button" class="btn btn-default">Some button</button>
      <ul class="dropdown-menu dropdown-menu-right">
        <ng-container *ngFor="let item of menuItems">
          <ng-container *ngTemplateOutlet="item.content"></ng-container>
        </ng-container>
      </ul>
    </div>
  `
})
export class PanelMenuComponent {
  @ContentChildren(PanelMenuItemComponent) menuItems: QueryList<PanelMenuItemComponent>;

  constructor(private cdRef: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.cdRef.detectChanges();
  }
}

我正在使用@ContentChildren来获取我们的面板菜单项,然后使用内置指令NgTemplateOutlet将内容放在ul中。

我们必须使用this.cdRef.detectChanges();运行第二个摘要周期,因为我们会收到错误

  

ExpressionChangedAfterItHasBeenCheckedError:表达式已更改   检查后。上一个值:'undefined'。当前值:   '[object Object]'。

@ViewChild(TemplateRef) content在更改检测期间更新其值。

<强> Stackblitz Example