从数据API动态创建递归树形视图的最佳方法

7

我正在学习Angular 2,尝试从(可能非常大的)第三方API构建可扩展的树形视图。该API具有以下基本结构:

- Home (id: 1053)
- - Rugby League (id: 1054)
- - - Super League (id: 1103)
- - - - Castleford Tigers (id: 1111)
- - - - Catalans Dragons (id: 1110)
- - - - Huddersfield Giants (id: 1116)
- - - - Hull FC (id: 1108)
- - - Championship (id: 1104)
- - - - Batley Bulldogs (id: 1120)
- - - - Bradford Bulls (id: 1118)
- - - - Dewsbury Rams (id: 1124)
- - - - Featherstone Rovers (id: 1121)
- - Football (id: 1056)
- - - Premier League (id: 1057)
- - - - AFC Bournemouth (id: 1059)
- - - - etc
- - - - etc

API被设置成当我传递一个id时,它返回该节点的子节点的简单JSON数组。例如,我调用:http://www.example.com/api/contentNodes/?parentId=1053,它将返回如下内容:
[
  {"Id":1054,"Name":"Rugby League","HasChildren":true},
  {"Id":1056,"Name":"Football","HasChildren":true}
]

(HasChildren表示节点是否具有子节点。)

请注意,由于数据集最终将变得很大,因此我希望在树形分支被打开时逐步从API中“拉出”更多数据,而不是将整个数据集倾泻进去并在我的应用程序中呈现出来。

我已经设置了一个Angular 2应用程序,可以在这里看到:http://plnkr.co/edit/QQ1OKCbd4pDptpSVbWch?p=preview

关键组件是`app/content-list.component.ts'文件:

import {Component, OnInit}  from 'angular2/core';
import {ContentNode}        from './content-node';
import {ContentService}     from './content.service';

@Component({
    selector: 'content-list',
    template: `
        <ol class="tree">
            <li *ngFor="#contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}">
                <a *ngIf="contentNode.HasChildren" (click)="toggleBranch(contentNode.Id)" class="toggle">+</a> {{ contentNode.Name }}
            </li>
        </ol>
        <div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
    `
})
export class ContentListComponent implements OnInit {

    constructor (private _contentService: ContentService) {}

    errorMessage: string;
    private _startNodeId: number = 1053;

    contentNodes: ContentNode[];

    ngOnInit() { 
        this.getContentNodes();
    }

    getContentNodes() {
        this._contentService.getContentNodes(this._startNodeId)
            .subscribe(
                contentNodes => this.contentNodes = contentNodes,
                error =>  this.errorMessage = <any>error
            );
    }

    toggleBranch(branchId:number){
        console.log('branchId: ' + branchId);
    }
}

您可以看到我在调用服务时传递了parentId为1053, 并返回了如上所述的JSON数据。
现在,当单击“+”按钮时,我无法逐步加载树形视图的子节点到嵌套的HTML列表(
    )中,遇到了一些困难。
    在这里,最好的方法是什么,以便以一种真正简洁的方式实现此目标?
    我的下一步将是确保应用程序不进行过多的API调用,但我目前的关注点只是让树形视图运行并正常工作。
    我已经看过这个递归树形视图的例子,但它似乎(a)有点错误(即在子节点为空时渲染了空的
      元素); (b)它似乎是以一种非常“硬编码”的方式设置的,而我没有足够的经验来自信地重构它。
      谢谢。
      注意,出于安全原因,我无法公开API进行测试,这使得在Plunkr上测试有些困难,对此我表示歉意。目前,我的示例仅使用静态的单层JSON数据集。
    1个回答

    8
    在Angular2中,您可以递归地呈现指令。这使得呈现树变得非常容易。 我稍微修改了您的 Plunker ,只是为了说明这一点。这不是理想的实现方式,但它能够正常工作:)。
    例子:
    @Component({
        selector: 'tree-view',
        template: `
            <div *ngFor="#dir of dirs">
                <tree-view [dirs]="dir.dirs"></tree-view>
            <div>
        `,
        directives: [TreeView]
    })
    export class TreeView {
        @Input() 
        private dirs: Array<Directory>;
    }
    

    我希望您会喜欢它。

    干杯!


    好的!谢谢。非常想知道理想的实现方式是什么,因为我的应用程序将在很大程度上依赖于这个逻辑。如果你有时间解释一下,那就太感激了,但无论如何,还是感谢你提供的可行解决方案! :) - Dan
    这将是一个非常有趣的案例,可以通过变化检测来解决 :) - Sam Vloeberghs

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接