Как сделать дерево с загрузкой данных по требованию? - PullRequest
0 голосов
/ 03 июня 2019

Как сделать дерево с загрузкой данных по запросу? У меня есть бэкенд, какой метод возвращает мне узлы корневого уровня, а другой метод возвращает мне детей родителей по идентификатору родителей. Я хочу построить дерево, в котором я нажимаю на узел и загружаю данные дерева и рисую для меня новую ветку с детьми и так далее. Я не знаю, как глубоко это дерево будет. Как это реализовать с помощью mat-tree? Я пробовал рекурсивную функцию * ngFor, но она не работает с mat-tree. Я хочу что-то вроде этого ссылка , но без каких-либо внешних библиотек

1 Ответ

1 голос
/ 04 июня 2019

ну я создаю сервис с двумя функциями

getRootNodes(){}

и

getChildren(node:any){}

getRootNodes, возвращает первый уровень root.

getChildren (узлов: любой), вернуть «потомков». Но я не только возвращаю массив строк, но и возвращаю массив объектов с свойством isExpandable. Для материала-дерева необходимо знать, когда у детей есть дети

Следующим изменением является использование нашего сервиса в DinamicDataSource. Наш toggleNode должен использовать сервис. Если! extends - это код, который был в setTimeOut, ну, конечно, нам не нужен setTimeOut.

Если раскрыть = true, мы вызываем сервис и подписываемся на данные. В подписку код под setTimeOut.

Обратите внимание, что в обоих случаях нам нужно вызвать this.dataChange.next (this.data)

toggleNode(node: DynamicFlatNode, expand: boolean) {
    const index = this.data.indexOf(node);
    if (!expand)
    {
      let count = 0;
        for (let i = index + 1; i < this.data.length
          && this.data[i].level > node.level; i++, count++) {}
        this.data.splice(index + 1, count);
        this.dataChange.next(this.data);
    }
    else
    {
    node.isLoading = true;
    this.dataService.getChildren(node.item).subscribe(children=>{
      if (!children || index < 0) { // If no children, or cannot find the node, no op
        node.isLoading = false;

        return;
      }
      if (expand) {
        const nodes = children.map(obj =>
          new DynamicFlatNode(obj.name, node.level + 1, obj.isExpandable));
        this.data.splice(index + 1, 0, ...nodes);
      }
      node.isLoading = false;
      // notify the change
      this.dataChange.next(this.data);

    })
    }
  }

Последнее изменение - это передача ngOnInit функций конструктора в TreeDynamicExample

ngOnInit()
  {
    this.treeControl = new FlatTreeControl<DynamicFlatNode>(this.getLevel, this.isExpandable);
    this.dataSource = new DynamicDataSource(this.treeControl, this.dataService);
    this.dataService.getRootNodes().subscribe(res=>{
      this.dataSource.data = res.map(name => new DynamicFlatNode(name, 0, true));
    })
  }

Обратите внимание, что прежде чем сравнивать this.dataSourceData с DynamicFlatNode, нам нужно получить данные и сделать их в подписке

Обновление : демистификация источника DinamicData.

Ну, чтобы понять древовидную динамику, мы можем взглянуть на то, что является «данными» в источнике DynamicData. Эти данные это всего лишь массив объектов со свойствами: item, level, расширяемый и загружаемый. Итак, это выглядит как

[
{item: "Fruits",level:0,expandable:true,isLoading:false},
{item: "Apple",level:1,expandable:true,isLoading:false},
{item: "Orange",level:1,expandable:false,isLoading:false},
{item: "Bannana",level:1,expandable:false,isLoading:false},
{item: "Vegetables",level:0,expandable:true,isLoading:false}
]

Да, это просто массив. Но это упорядоченный массив. Таким образом, мы можем создать функцию addNode в нашем DinamicDataSource, например

  addSubNode(index:number,name:string,isExpandable:boolean)
  {
     const node=this.data[index];
     const dfn={item: name,
         level:node.level+1,
         expandable:isExpandable,
         isLoading:false}
     this.data.splice(index + 1, 0, ...[dfn]);
     this.dataChange.next(this.data);
  }

  addNode(index:number,name:string,isExpandable:boolean)
  {
     const node=this.data[index];
     const dfn={item: name,
         level:node.level,
         expandable:isExpandable,
         isLoading:false}
     this.data.splice(index + 1, 0, ...[dfn]);
     this.dataChange.next(this.data);
  }

  changeNode(index:number,name:string)
  {
     this.data[index].item=name;
  }

Обратите внимание, что после изменения массива с добавлением узла / подузла нам нужно вызвать this.dataChange.next (this.data), потому что сплайс изменяет «содержимое» массива, но не сам массив. Мы также можем сделать некоторые "bizarro" как

 this.data=[...this.data]

но ребята из Angular Material облегчают нам жизнь, и мы можем использовать .next (это причина, потому что данные на самом деле не массив, а значение BehaviorSubject)

Я надеюсь, что это восклицание уберет "магию" из динамического дерева. Я разветвлял стек , чтобы добавить в дерево простые кнопки, чтобы добавить узел, добавить подузел и изменить узел

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...