Angular 2: рекурсивный шаблон для ребенка

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-уровни вниз по данным и, таким образом, оставлять жестко закодированный предел.

Как можно оптимизировать этот код, чтобы он поддерживал неограниченное количество уровней и выглядел лучше?


person Glenn Utter    schedule 30.01.2017    source источник


Ответы (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>

перейдите по здесь, чтобы ознакомиться с демонстрацией в реальном времени.

person lucas    schedule 22.08.2018
comment
привет, лукас, я не могу найти способ сделать редактирование по ссылке на живую демонстрацию. Не могли бы вы помочь? - person Feng Zhang; 01.05.2019
comment
@FengZhang для редактирования не требуются разрешения и т. д., вы можете попробовать разветвить свой или проверить консоль браузера, чтобы увидеть какие-либо ошибки. - person lucas; 03.05.2019

https://stackblitz.com/edit/angular-yij5e5?file=src%2Fapp%2Ftree-view%2Ftree-view.component.ts Примечание: приведенный ниже код не является рекурсивным, он двумерный и не может использоваться для рендеринга дерева. вы должны использовать шаблон 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>

[Решение 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;
      }
person Navid Golforoushan    schedule 21.08.2018