Mat-tree создает дерево со значениями для отображения и идентификаторами - PullRequest
0 голосов
/ 14 октября 2019

Я изучаю, как использовать mat-tree, следуя документам, но теперь мне нужно использовать дерево источника данных, в котором определены не только строки, потому что когда я щелкаю узел, мне нужно знать его идентификатор.
Это стек стека моего проекта .
По сути, мне нужно использовать это дерево с флажками, которые я построил по документам, но теперь мой источник данных такой:

const TREE_DATA:TodoItemNode = {
  item: "First item",
  children: [{
    item: 'Second item',
    children:[
      {
        item: "Third item",
        id: 3
      }
    ],
      id:2
    }],
  id:1
  }

Итак, я хочу отобразить в виде текста значение элемента, а затем получить «id» при нажатии на этот узел. В настоящее время я не могу заставить его работать, и я вижу только эти узлы дерева:

enter image description here

Есть ли рабочий пример для данных в виде JSON, со свойствами и т. Д. как я хочу добиться?

1 Ответ

1 голос
/ 15 октября 2019

Действительно, я верю, что пример с древовидной структурой более сложен. Представьте, что у вас есть что-то вроде

const TREE_DATA: FoodNode[] = [
  {
    name: "Fruit",
    children: [
      { name: "Apple", id: 1 },
      { name: "Banana", id: 2 },
      { name: "Fruit loops", id: 3 }
    ]
  },
  {
    name: "Vegetables",
    children: [
      {
        name: "Green",
        children: [
          { name: "Broccoli", id: 4 },
          { name: "Brussel sprouts", id: 5 }
        ]
      },
      {
        name: "Orange",
        children: [{ name: "Pumpkins", id: 6 }, { name: "Carrots", id: 7 }]
      }
    ]
  }
];

Если вы добавите в свой интерфейс FoodNode некоторые вспомогательные свойства: selected, parent и неопределенный

interface FoodNode {
  name: string;
  id?: number;
  selected?: boolean;
  indeterminate?:boolean;
  parent?:FoodNode
  children?: FoodNode[];
}

Ключ здесь - это знать «parent», поэтому, когда мы включаем одну проверку, спрашиваем о его родителе

  setParent(data, parent) {
    data.parent = parent;
    if (data.children) {
      data.children.forEach(x => {
        this.setParent(x, data);
      });
    }
  }

. Вы можете написать .html как

<mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree">
  <!-- This is the tree node template for leaf nodes -->
  <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
    <li class="mat-tree-node">
      <!-- use a disabled button to provide padding for tree leaf -->
      <button mat-icon-button disabled></button>
          <mat-checkbox class="checklist-leaf-node" 
            (change)="todoItemSelectionToggle($event.checked,node)" 
            [checked]="node.selected"
>{{node.name}}</mat-checkbox>
    </li>
  </mat-tree-node>
  <!-- This is the tree node template for expandable nodes -->
  <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
    <li>
      <div class="mat-tree-node">
        <button mat-icon-button matTreeNodeToggle
                [attr.aria-label]="'toggle ' + node.name">
          <mat-icon class="mat-icon-rtl-mirror">
            {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
          </mat-icon>
        </button>
            <mat-checkbox [checked]="node.selected"
                  [indeterminate]="node.indeterminate && !node.selected"
                  (change)="todoItemSelectionToggle($event.checked,node)">
            {{node.name}}</mat-checkbox>
      </div>
      <ul [class.example-tree-invisible]="!treeControl.isExpanded(node)">
        <ng-container matTreeNodeOutlet></ng-container>
      </ul>
    </li>
  </mat-nested-tree-node>
</mat-tree>

Другие функции:

  treeControl = new NestedTreeControl<FoodNode>(node => node.children);
  dataSource = new MatTreeNestedDataSource<FoodNode>();

  constructor() {
    this.dataSource.data = TREE_DATA;
    Object.keys(this.dataSource.data).forEach(x => {
      this.setParent(this.dataSource.data[x], null);
    });
  }

  hasChild = (_: number, node: FoodNode) =>
    !!node.children && node.children.length > 0;

  checkAllParents(node) {
    if (node.parent) {
      const descendants = this.treeControl.getDescendants(node.parent);
      node.parent.selected=descendants.every(child => child.selected);
      node.parent.indeterminate=descendants.some(child => child.selected);
      this.checkAllParents(node.parent);
    }
  }

  todoItemSelectionToggle(checked, node) {
    node.selected = checked;
    if (node.children) {
      node.children.forEach(x => {
        this.todoItemSelectionToggle(checked, x);
      });
    }
    this.checkAllParents(node);
  }
}
  submit() {
    let result = [];
    this.dataSource.data.forEach(node => {
      result = result.concat(
        this.treeControl
          .getDescendants(node)
          .filter(x => x.selected && x.id)
          .map(x => x.id)
      );
    });
    console.log(result);
  }

Stabblitz здесь

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