使用 json 对象列表以角度生成层次结构视图
Posted
技术标签:
【中文标题】使用 json 对象列表以角度生成层次结构视图【英文标题】:Generating a hierarchy view in angular with a list of json objects 【发布时间】:2019-10-14 07:26:34 【问题描述】:我目前正在尝试构建用户的层次结构视图。我的最终目标是使用this hierarchy view 生成视图 或类似的东西。
难点在于如何给出用于生成层次结构的 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,
]
为了更好地解释上面的响应,这里是它的视觉层次视图: image
到目前为止,我看到的许多答案和解决方案都使用 JSON,每个子节点都嵌套在其中。是否可以使用上面的 json 模型生成视图?
任何帮助或见解将不胜感激!谢谢!
【问题讨论】:
好吧。我是否正确,您需要从数据中获取图表(图表)? 是的,我需要一张图表。就像那个一样,我在第一段中链接了。 【参考方案1】:首先,您需要将自引用表转换为分层表(树)。我建议您使用custom pipe 来执行此操作,因为您将能够在其他地方重复使用此管道。
您可以使用 Reactgular 的代码、我来自 *** 线程的代码,或者编写您自己的代码。我用 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,展示了这种方法的实际应用。
【讨论】:
【参考方案2】:您可以使用 reducer 将平面数组转换为节点的 UID 映射,一旦您拥有映射,您就可以轻松地填充子节点。然后,您可以选择根节点并使用它来呈现 html。
const map = [
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,
].reduce((acc, node) => (node.children = [], acc[node.uid] = node, acc), );
const [root] = Object.values(map)
.map(node => (node.pid && map[node.pid].children.push(node), node))
.filter(node => node.pid === null);
console.log(root);
您可以使用相同的组件递归地渲染树,并让模板渲染孩子。
@Component(
selector: 'app-node',
template: `
<span>Node</span>
<app-node [node]="child" *ngFor="let child of node.children"></app-node>
`
)
export class NodeComponent
@Input()
public node: any;
修改上述内容以匹配您在问题中链接到的 HTML/CSS 并不难。
【讨论】:
以上是关于使用 json 对象列表以角度生成层次结构视图的主要内容,如果未能解决你的问题,请参考以下文章