使用 json 对象列表以角度生成层次结构视图

Aid*_*ido 3 html css json angular

我目前正在尝试构建用户的层次结构视图。我的最终目标是使用这个层次视图 或类似的东西生成视图。

难点在于如何给出用于生成层次结构的 JSON 对象。这是一个示例响应(此响应可以大得多),其中 pid 是父 id,depth 是与第一个父的距离。

response = [
    {uid: "abc", pid: null, depth: 1, parent: true},
    {uid: "def", pid: "abc", depth: 2, parent: false},
    {uid: "ghi", pid: "abc", depth: 2, parent: true},
    {uid: "jkl", pid: "ghi", depth: 3, parent: false},
    {uid: "mno", pid: "ghi", depth: 3, parent: false},
]
Run Code Online (Sandbox Code Playgroud)

为了更好地解释上述响应,这里是它的视觉层次结构视图: 图像

到目前为止,我看到的许多答案和解决方案都使用 JSON,每个都嵌套有子级。是否可以使用上面的 json 模型生成视图?

任何帮助或见解将不胜感激!谢谢!

Gos*_*ten 7

首先,您需要将您的自引用表转换为分层表(树)。我建议您使用自定义管道来执行此操作,因为您可以在其他地方重复使用此管道。

您可以使用 Reactgular 的代码、我来自StackOverflow线程的代码,或者编写您自己的代码。我converter用 Reactgular 的代码创建了我的管道:

转换器.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);
  }
}
Run Code Online (Sandbox Code Playgroud)

不要忘记将其添加到declaration模块的部分:

app.module.ts

import { ConverterPipe } from './converter.pipe';

@NgModule({
  declarations: [
    ConverterPipe
  ]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

现在,您可以创建组件模板并使用来自Hierarchy View CodePen 的方法。由于您需要为分支和叶子使用不同的标记,因此使用NgTemplateOutlet'sNgIf结构指令很方便。这是在模板中移动关卡标记并在需要在 Angular 中渲染树时重用它的好主意。我的回答说明了同样的想法。根据提供的 CodePen 代码,您的 Angular 标记可能如下所示:

应用程序组件.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>
Run Code Online (Sandbox Code Playgroud)

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 }
  ];
}
Run Code Online (Sandbox Code Playgroud)

不要忘记在您的项目中使用 CodePen SASS 样式。

在此之后,您将得到如下图:

图形

这是一个StackBlitz 项目,它演示了这种方法的实际应用。