Angular @ContentChildren不能与<ng-template>一起使用

时间:2018-01-10 10:37:05

标签: angular recursion angular-template

我正在尝试在Angular中创建一个Tree组件,如下所示:

@Component({
  selector: 'app-tree',
  template: `
    <div style.padding-left.px="{{depth*20}}">
      <ng-content></ng-content>
    </div>
  `
})
export class TreeComponent implements AfterContentInit {
  private _depth = 0;
  get depth() {
    return this._depth;
  }
  set depth(value: number) {
    this._depth = value;
    this.updateChildren();
  }

  @Input() isRoot: boolean;

  @ContentChildren(TreeComponent) children: QueryList<TreeComponent>;

  ngAfterContentInit() {
    if (this.isRoot) {
      console.log('i am root', this.children.filter(tree => tree !== this).length);
      this.updateChildren();
    }
  }

  private updateChildren() {
    this.children
      .filter(tree => tree !== this)
      .forEach(branch => {
        branch.depth = this.depth + 1;
      });
  }
}

使用带有标记的组件时,这样可以正常工作。像这样:

<app-tree [isRoot]="true">
  Label 1
  <app-tree>
    Label 1.1
  </app-tree>
  <app-tree>
    Label 1.2
    <app-tree>
      Label 1.2.1
    </app-tree>
  </app-tree>
  <app-tree>
    Label 1.3
  </app-tree>
</app-tree>

但是在根据数据渲染树时失败,例如:

<ng-template #treeTemplate let-tree let-root="isRoot">
  <app-tree *ngFor="let node of tree" [isRoot]="root">
    {{ node.text }}
    <ng-container *ngTemplateOutlet="treeTemplate; context:{$implicit:node.children}"></ng-container>
  </app-tree>
</ng-template>
<ng-container *ngTemplateOutlet="treeTemplate; context:{$implicit:treeModel, isRoot:true}"></ng-container>

此代码基于模型递归呈现树节点,模型可能是这样的:

treeModel = [
  {
    text: 'Lorem ipsum',
    children: [
      {
        text: 'Lorem ipsum',
        children: [
          {
            text: 'Lorem ipsum',
            children: [
              { text: 'Lorem ipsum' },
              { text: 'Lorem ipsum' },
              { text: 'Lorem ipsum' }
            ]
          },
          { text: 'Lorem ipsum' },
          { text: 'Lorem ipsum' },
          { text: 'Lorem ipsum' }
        ]
      },
      { text: 'Lorem ipsum' },
      { text: 'Lorem ipsum' },
      { text: 'Lorem ipsum' }
    ]
  }
];

这不起作用,因为从模板渲染树。看来,当将组件包装在ng-template中时,@ContentChildren无法找到从模板呈现的子项。

这是预期的吗?任何可能的解决方案,解决方法?

另一个问题(虽然问题较少)是ContentChildren包含主机组件;因此this.children.filter(tree => tree !== this)

链接到Plunker:https://embed.plnkr.co/jRXk8eI0mz7db6eliMoj/

1 个答案:

答案 0 :(得分:0)

There is an Open issue in Angular for this problem.

In the link the person who reports the issue provides a workaround, but I find it rather cumbersome and I believe it can lead to poor performance.

相关问题