【问题标题】:Angular 6 Material TreeAngular 6 材质树
【发布时间】:2018-06-12 04:43:16
【问题描述】:

我正在尝试根据docs 制作一个材质角度树,但似乎遇到了一个我似乎无法诊断的错误。 Chromes 在我的 HTML 第 8 行给出了 Cannot read property 'children' of undefined 的错误。看起来好像树被加载到 nestedDataSource 就好了,但它不会显示任何东西。诚然,我不完全确定 Angular Material 树是如何工作的,所以我可能只是弄乱了 html。

角度 6.01

category-picker.component.html:

<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="category-picker">
  <mat-tree-node *matTreeNodeDef="let node">
    <li class="mat-tree-node">
      {{node.category.name}}
    </li>
  </mat-tree-node>

  <mat-nested-tree-node *matTreeNodeDef="let node; when: node.children.length">
    <li>
      {{node.category.name}}
      <ul [class.example-tree-invisible]="!nestedTreeControl.isExpanded(node)">
        <ng-container matTreeNodeOutlet></ng-container>
      </ul>
    </li>
  </mat-nested-tree-node>
</mat-tree>

category-picker.component.ts:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import {NestedTreeControl} from '@angular/cdk/tree';

import {MatSelectModule} from '@angular/material';
import {MatTreeNestedDataSource} from '@angular/material/tree';

import { DataBrokerService } from '../data-broker.service';
import { Category } from '../datatypes'
import { observable, of } from 'rxjs';

export class CategoryNode {
  children: CategoryNode[];
  category: Category;
}


@Component({
  selector: 'app-category-picker',
  templateUrl: './category-picker.component.html',
  styleUrls: ['./category-picker.component.scss']
})
export class CategoryPickerComponent implements OnInit {

  // Does not follow main/sub category - just has a simple category!
  @Input() categoryID: number;
  @Output() categoryIDChange:EventEmitter<number> = new EventEmitter<number>();

  nestedTreeControl: NestedTreeControl<CategoryNode>;

  nestedDataSource: MatTreeNestedDataSource<CategoryNode>;

  constructor(
    private dataBrokerService: DataBrokerService
  ) { 
    this.nestedTreeControl = new NestedTreeControl(node => of(node.children));
    this.nestedDataSource = new MatTreeNestedDataSource();
  }

  ngOnInit() {
    this.dataBrokerService.getCategories().subscribe(categories => this.nestedDataSource.data = this.buildTree(categories));
  }

  onChange(){
    this.categoryIDChange.emit(this.categoryID);
  }

  private buildTree(categories:Category[]):CategoryNode[]{
    console.log("tree");

    let tree:CategoryNode[] = [];
    let map: {[s:number]: CategoryNode} = {};

    // Build an index of the nodes
    categories.forEach(cat => {
      map[cat.id] = {children:[], category:cat};
    });

    // Start adding nodes to tree 
    for (let key of Object.keys(map)){
      let catNode = map[+key];

      if (map[catNode.category.parent_id]){
        // Add it to the parent
        map[catNode.category.parent_id].children.push(catNode);
      }
      else{
        // Add it to root
        tree.push(catNode);
      }
    };
    console.log(tree);
    return tree;
  }
}

【问题讨论】:

  • 检查节点树的子属性。
  • 树形结构很好,谢谢!

标签: angular angular-material


【解决方案1】:

原来我错误地实现了MatTreeNodeDef的'when'函数。在我的 HTML 中,我需要将 when: node.children.length 更改为 when: hasNestedChild,它在 .ts 文件中定义为 = (_: number, nodeData) =&gt; {return nodeData.children.length}。换句话说,when 是一个必需参数,它采用具有 两个 输入(数字和节点)的函数。

【讨论】:

  • 很高兴您能解决您的问题!您可能想用复选标记将自己的答案标记为正确,以帮助未来的访问者并帮助回答者识别实际已解决的问题。
  • 好点,我必须等到明天才能接受我的回答:D
  • 如何向树中添加新元素?
【解决方案2】:

category-picker.component.html: &lt;mat-nested-tree-node *matTreeNodeDef="let node; when: hasNestedChild"&gt;

category-picker.component.ts: hasNestedChild=(_: number, nodeData) =&gt; {return nodeData.children.length}

【讨论】:

  • 欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
猜你喜欢
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 2018-11-24
  • 1970-01-01
  • 2020-11-11
  • 2019-08-30
相关资源
最近更新 更多