如何在Angular Material嵌套树中获取节点兄弟?

时间:2019-05-07 13:37:17

标签: angular typescript angular-material2 angular-cdk

我正在尝试获取嵌套树中给定Angular Material树节点的兄弟节点列表。

我正在经历Angular Material官方docs,并且特别涉猎“带有嵌套节点的树”。我无法通过NestedTreeControl访问的SelectionModel@angular/cdk/collections都没有提供访问或查看给定节点的同级节点的方法。除非您使用的是扁平树,否则它们甚至都无法提供知道节点所在的NESTED树的级别的方法。

这是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>
      {{node.name}}
    </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>
        {{node.name}}
      </div>
      <ul [class.example-tree-invisible]="!treeControl.isExpanded(node)">
        <ng-container matTreeNodeOutlet></ng-container>
      </ul>
    </li>
  </mat-nested-tree-node>
</mat-tree>

这是课程代码

import {NestedTreeControl} from '@angular/cdk/tree';
import {Component} from '@angular/core';
import {MatTreeNestedDataSource} from '@angular/material/tree';

/**
 * Food data with nested structure.
 * Each node has a name and an optiona list of children.
 */
interface FoodNode {
  name: string;
  children?: FoodNode[];
}

const TREE_DATA: FoodNode[] = [
  {
    name: 'Fruit',
    children: [
      {name: 'Apple'},
      {name: 'Banana'},
      {name: 'Fruit loops'},
    ]
  }, {
    name: 'Vegetables',
    children: [
      {
        name: 'Green',
        children: [
          {name: 'Broccoli'},
          {name: 'Brussel sprouts'},
        ]
      }, {
        name: 'Orange',
        children: [
          {name: 'Pumpkins'},
          {name: 'Carrots'},
        ]
      },
    ]
  },
];

/**
 * @title Tree with nested nodes
 */
@Component({
  selector: 'tree-nested-overview-example',
  templateUrl: 'tree-nested-overview-example.html',
  styleUrls: ['tree-nested-overview-example.css'],
})
export class TreeNestedOverviewExample {
  treeControl = new NestedTreeControl<FoodNode>(node => node.children);
  dataSource = new MatTreeNestedDataSource<FoodNode>();

  constructor() {
    this.dataSource.data = TREE_DATA;
  }

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

和一些CSS

.example-tree-invisible {
  display: none;
}

.example-tree ul,
.example-tree li {
  margin-top: 0;
  margin-bottom: 0;
  list-style-type: none;
}

我只需要一种访问兄弟节点的方法。我还真的需要根据使用NESTED树时所在的节点知道我处于哪个级别。

1 个答案:

答案 0 :(得分:0)

对于任何寻求答案的人,我解决了以下问题。

  1. 首先为节点类创建自定义数据属性。 现在这是我的节点类:

import {NestedTreeControl} from '@angular/cdk/tree';
import {Component} from '@angular/core';
import {MatTreeNestedDataSource} from '@angular/material/tree';

/**
 * Food data with nested structure.
 * Each node has a name and an optional list of children.
 */
interface FoodNode {
  name: string;
  children?: FoodNode[];
}

export class FoodNode {
  children: BehaviorSubject<FoodNode[]>;
  constructor(
    public name: string,
    public type: string,
    public id: number,
    children?: FoodNode[],
    public parent?: FoodNode,
    public level = 0
  ) {
    this.children = new BehaviorSubject(children === undefined ? [] : children);
  }
}

  1. 第二个嵌套树类如下
import { NestedTreeControl } from '@angular/cdk/tree';

export class NestedTreeComponent implements OnInit, OnDestroy {
  // TREE CONTROLS
  treeControl: NestedTreeControl<FoodNode>;
  foodTreeLevels = [];
  treeDepth = 1; // initialize tree with default depth 1

  ngOnInit() {
   // initialize tree controls and data source
   this.treeControl = new NestedTreeControl<FoodNode>(this.getChildren);
  }

  /** Get node children */
  getChildren = (node: FoodNode): Observable<FoodNode[]> => node.children;

  /**
   * @desc Add the node to its parent's children object
   */
  addNewFood(parent: FoodNode, foodName: string, foodType: string, foodId: number) {
    // Add the food to the list of children
    const child = new FoodNode(foodName, foodType, foodId, [], parent, 0);
    child.level = parent.level + 1;
    // add a new level to the tree if the parent of this node has no children yet
    if (parent && parent.children.value.length === 0 && !this.foodTreeLevels.includes(child.level)) {
      this.foodTreeLevels.push(child.level);
      this.treeDepth += 1;
    }
    // update the parents' children with this newly added node if the parent exists
    if (parent) {
      const children = parent.children.value;
      children.push(child);
      parent.children.next(children);
   }

  }
  1. 现在,无论您需要访问树中任何节点的同级节点,只需转到节点的父节点,然后按以下方式获取其所有子节点:
// This is a node of type FoodNode
const parent = theNodeINeedToGetSiblingsFor.parent; 
const siblings = parent.children.value;