首先,您需要将自引用表转换为分层表(树)。我建议您使用custom pipe 来执行此操作,因为您将能够在其他地方重复使用此管道。
您可以使用 Reactgular 的代码、我来自 StackOverflow 线程的代码,或者编写您自己的代码。我用 Reactgular 的代码创建了我的 converter 管道:
converter.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'converter'
})
export class ConverterPipe implements PipeTransform {
transform(array: any[], id: string = 'uid', parentId: string = 'pid'): any[] {
const map = array.reduce(
(acc, node) => ((node.items = []), (acc[node[id]] = node), acc),
{}
);
return Object.values(map)
.map(
node => (node[parentId] && map[node[parentId]].items.push(node), node)
)
.filter(node => node[parentId] === null);
}
}
不要忘记将其添加到模块的 declaration 部分:
app.module.ts
import { ConverterPipe } from './converter.pipe';
@NgModule({
declarations: [
ConverterPipe
]
})
export class AppModule { }
现在,您可以创建组件模板并使用Hierarchy View CodePen 中的方法。由于您需要为树枝和树叶使用不同的标记,因此使用NgTemplateOutlet's 和NgIf structural directives 很方便。当您需要在 Angular 中渲染树时,在模板中移动关卡标记并重用它是一个好主意。我的answer 说明了相同的想法。根据提供的 CodePen 代码,您的 Angular 标记可能如下所示:
app.component.html
<div class="hv-wrapper">
<ng-template #Item let-item>
<ng-container *ngIf="!item.items.length; else Component">
<p>{{ item.uid }}</p>
</ng-container>
<ng-template #Component>
<div class="hv-item">
<div class="hv-item-parent">
<p>{{ item.uid }}</p>
</div>
<div class="hv-item-children">
<div class="hv-item-child" *ngFor="let child of item.items">
<ng-container
*ngTemplateOutlet="Item; context: { $implicit: child }"
></ng-container>
</div>
</div>
</div>
</ng-template>
</ng-template>
<ng-container *ngFor="let child of response | converter"
><ng-container
*ngTemplateOutlet="Item; context: { $implicit: child }"
></ng-container
></ng-container>
</div>
这里,response 是您的原始数组:
app.component.ts
export class AppComponent {
response = [
{ uid: 'abc', pid: null, depth: 1, parent: true },
{ uid: 'def', pid: 'abc', depth: 2, parent: true },
{ uid: 'ghi', pid: 'abc', depth: 2, parent: false },
{ uid: 'jkl', pid: 'ghi', depth: 3, parent: false },
{ uid: 'mno', pid: 'ghi', depth: 3, parent: false }
];
}
不要忘记在您的项目中使用 CodePen SASS 样式。
在此之后,您将得到如下图:
这是一个StackBlitz project,展示了这种方法的实际应用。