How to filter a mat-tree component Angular Material 6.0.1

前端 未结 4 627
醉酒成梦
醉酒成梦 2020-12-28 08:47

I\'m using mat-tree angular material component. It\'s a nice component with some very useful features like, multi-select, expand all/collapse all. I was not able to find any

4条回答
  •  青春惊慌失措
    2020-12-28 09:23

    After I have spent several days on the same task here are some tips i can give: I am using input event to follow the user input:

    
    

    On this filter I attached a subject so i can subscribe to it:

    searchFilter: Subject = new Subject();
    filterChanged(filter: string): void {
      this.searchFilter.next(filter);
    }
    

    To make it smooth for the user, usually, we want to delay the search execution which you can do with debounceTime.

    this.searchFilter.pipe(debounceTime(500), distinctUntilChanged())
      .subscribe(value => {
        if (value && value.length >= 3) {
          this.filterByName(value);
        } else {
          this.clearFilter();
        }
    });
    

    To perform the search, I hide and show the nodes using a css class. This is done directly on the presentation collection which is flat and very easy to filter.

    treeControl: FlatTreeControl;
    this.treeControl.dataNodes
    

    First, I hide all and then show only those that match the criteria. Finally, I want to show their parents, but this is specific for my tree structure.

    private filterByName(term: string): void {
      const filteredItems = this.treeControl.dataNodes.filter(
        x => x.value.DisplayName.toLowerCase().indexOf(term.toLowerCase()) === -1
      );
      filteredItems.map(x => {
        x.visible = false;
      });
    
      const visibleItems = this.treeControl.dataNodes.filter(
        x => x.value.IsSkill &&
        x.value.DisplayName.toLowerCase().indexOf(term.toLowerCase()) > -1
      );
      visibleItems.map( x => {
        x.visible = true;
        this.markParent(x);
      });
    }
    

    Finally, here is the clear filter:

    private clearFilter(): void {
      this.treeControl.dataNodes.forEach(x => x.visible = true);
    }
    

    Don't make the same mistake like I did and try to filter the input collection (this.dataSource.data in my case) because you will lose your selection or you will have to map it back to the presentation. Here is my initial data:

    this.treeFlattener = new MatTreeFlattener(
      this.transformer, this._getLevel, this._isExpandable, this._getChildren
    );
    this.treeControl = new FlatTreeControl(
      this._getLevel, this._isExpandable
    );
    this.dataSource = new MatTreeFlatDataSource(
      this.treeControl, this.treeFlattener
    );
    
    skillService.dataChange.subscribe(data => {
      this.dataSource.data = data;
    });
    

提交回复
热议问题