Angular 2:孩子的递归模板

Posted

技术标签:

【中文标题】Angular 2:孩子的递归模板【英文标题】:Angular 2: Recursive template for child 【发布时间】:2017-06-15 19:00:52 【问题描述】:

我正在使用的 API 为我提供了以下结构作为响应:

"data": [

  "id": 5,
  "name": "First name",
  "parent": 0
,

  "id": 1,
  "name": "Second name",
  "parent": 5
,

  "id": 6,
  "name": "Third name",
  "parent": 1
,

  "id": 15,
  "name": "Fourth name",
  "parent": 0
,

  "id": 25,
  "name": "Fifth name",
  "parent": 5

]

我想围绕这个使用ngFor 构建一个树形结构,它支持无限数量的子级别。

这是我迄今为止尝试过的:

<div *ngFor="let d1 of _dataList">
<ul *ngIf="d1.parent == 0">
    <li>
        d1.name
        <ul *ngFor="let d2 of _dataList">
            <li *ngIf="d2.parent == d1.id">d2.name</li>
        </ul>
    </li>
</ul>
</div>

这行得通,但它很难看,我必须手动重复这个 X 级别的数据,从而留下硬编码的限制。

如何优化此代码以支持无限级别 - 并且看起来更好?

【问题讨论】:

这可能有助于***.com/questions/37746516/… 我宁愿说它是重复的 Use component in itself recursively to create a tree的可能重复 您需要格式化您的数据并使用递归结构,如上面链接的问题。您可能应该对其进行格式化,以便每个具有子节点的节点都将它们放在一个数组中,然后您可以更轻松地递归传递数据。 谢谢 Seiyria,我会研究让 API 以不同格式返回列表的可能性。 【参考方案1】:

https://stackblitz.com/edit/angular-yij5e5?file=src%2Fapp%2Ftree-view%2Ftree-view.component.ts 注意:下面的代码不是递归的,它是 2d 的,不能用于树渲染。 您应该使用 ng 模板或为其定义一个组件。

<div *ngFor="let d1 of _dataList">
<ul *ngIf="d1.parent == 0">
    <li>
        d1.name
        <ul *ngFor="let d2 of _dataList">
            <li *ngIf="d2.parent == d1.id">d2.name</li>
        </ul>
    </li>
</ul>
</div>
来自http://odyniec.net/articles/turning-lists-into-trees/的css 角度来自https://gist.github.com/arniebradfo/5cf89c362cc216df6fc1d9ca4d536b72 js(如何将平面数组转换为树)来自我:D

[解决方案 1]=>

JS

let xTree = [
                "id": 5,
                "name": "First name",
                "parent": 0
            ,
            ...
        ];
        let tree = [
            id: 0,
            name: 'root',
            parent: null,
            childs: []
        ];
        let todoList = [];
        Converter();
        function FindParent(list, el) 
            if (list.length > 0) 
                let res = list.find(x => x.id === el.parent);
                if (res) 
                    return res;
                 else 
                    let _res = undefined;
                    list.forEach(xchild => 
                        _res = FindParent(xchild.childs, el);
                        if (res)
                            return _res;
                    );
                    return _res
                
             else 
                return undefined;
            
        

        function Converter() 
            todoList = xTree;
            for (let x = 0; x < 90; x++) 
                todoList.forEach(r => 
                    let parent = FindParent(tree, r);
                    if (parent) 
                        if (!parent.childs) 
                            parent.childs = [];
                        
                        parent.childs.push(r);
                        todoList = todoList.filter(el => el !== r);
                    
                );
            
        

html

<ul class="tree">
  <ng-template #recursiveList let-list="list">
    <li *ngFor="let item of list">
      item.name
      <ul *ngIf="item.childSet.length > 0">
        <ng-container *ngTemplateOutlet="recursiveList; context: list: item.data"></ng-container>
      </ul>
    </li>
  </ng-template>
  <ng-container *ngTemplateOutlet="recursiveList; context: list: data"></ng-container>
</ul>

css

ul.tree, ul.tree ul 
  list-style-type: none;

  ul.tree, ul.tree ul 
    list-style-type: none;
    background: url(/assets/vline.png) repeat-y;
    margin: 0;
    padding: 0;
  

    ul.tree ul 
      margin-left: 10px;
    

    ul.tree li 
      margin: 0;
      padding: 0 12px;
      line-height: 20px;
      background: url(/assets/node.png) no-repeat;
      color: #369;
      font-weight: bold;
    

      ul.tree li:last-child 
        background: #fff url(/assets/lastnode.png) no-repeat;
      

【讨论】:

【参考方案2】:

你可以有一个递归组件,比如名为TreeComponent的组件 TreeComponent 的模板会是这样的

<div *ngFor="let item of dataList">
  <ul *ngIf="item.parent==parentId">
    <li>item.name
      <tree [parentId]="item.id" [dataList]="removeCurrentLevelItems(dataList,parentId)"></tree>
    </li>
  </ul>
</div>

查看link here 以获得现场演示

【讨论】:

嗨,卢卡斯,我找不到从现场演示链接进行编辑的方法。你能帮忙吗? @FengZhang 它不需要权限等进行编辑,您可以尝试分叉到您的一个或检查您的浏览器控制台以查看任何错误

以上是关于Angular 2:孩子的递归模板的主要内容,如果未能解决你的问题,请参考以下文章

Angular 在模板中创建递归循环以呈现评论树

Angular 9 - 渲染有限数量的组件的孩子

Angular 指令中的递归

Angular 4 - 将对象数组映射到模板中的 ngModel 驱动

初始化所有孩子后的Angular 2生命周期钩子?

Angular2 - 父母和孩子通过服务进行交流