我正在尝试在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/
答案 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.