如何过滤mat-tree组件Angular Material 6.0.1

时间:2018-05-30 18:56:21

标签: angular filter tree angular6 angular-material2

我正在使用mat-tree角材料组件。 这是一个很好的组件,有一些非常有用的功能,如多选,全部展开/全部折叠。 我无法在任何API中找到任何树过滤功能。 有没有人遇到过这个功能或者做过任何工作来获得mat-tree过滤器?

enter image description here

6 个答案:

答案 0 :(得分:5)

我通过创建一个新的数据源(已过滤)解决了这个问题。

stackblitz sample

我将解释共享链接的示例:我在filter(filterText: string)中用ChecklistDatabase过滤了数据并触发了dataChange事件。然后datasource.dataTreeChecklistExample中的已处理事件更改。因此,数据源已被修改。

filter(filterText: string) {
  let filteredTreeData;

  if (filterText) {
    filteredTreeData = this.treeData.filter(
      //There is filter function in the sample
    );
  } else {
    filteredTreeData = this.treeData;
  }

  // file node as children.
  const data = this.buildFileTree(filteredTreeData, '0');

  // Notify the change. !!!IMPORTANT
  this.dataChange.next(data);
}

答案 1 :(得分:4)

我花了几天时间完成同一任务后,这里提供一些提示: 我正在使用输入事件来跟踪用户输入:

<com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:roundedCornerRadius="8dp"
                android:adjustViewBounds="true"
                android:scaleType="fitXY"

                />

在此过滤器上,我附加了一个主题,因此我可以订阅它:

<input matInput class="form-control" 
  (input)="filterChanged($event.target.value)" 
  placeholder="Search Skill">

通常来说,为了使用户使用起来更加顺畅,我们希望延迟执行searchFilter: Subject<string> = new Subject<string>(); filterChanged(filter: string): void { this.searchFilter.next(filter); } 才能执行的搜索。

debounceTime

要执行搜索,我使用CSS类隐藏和显示节点。直接在扁平且易于过滤的演示文稿集合上完成此操作。

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

首先,我隐藏所有内容,然后仅显示那些符合条件的内容。最后,我想向他们的父母展示,但这是针对我的树形结构的。

treeControl: FlatTreeControl<SkillFlatNode>;
this.treeControl.dataNodes

最后,这是清除过滤器:

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);
  });
}

不要像我一样犯同样的错误,并尝试过滤输入集合(在我的情况下为private clearFilter(): void { this.treeControl.dataNodes.forEach(x => x.visible = true); } ),因为您会丢失选择,或者必须将其映射回演示文稿。 这是我的初始数据:

this.dataSource.data

答案 2 :(得分:1)

我能够通过使用简单的递归来过滤树。以下是代码段:

filter()的{​​{1}}上调用(keyup)函数。 input type="text"函数是从lodash cloneDeep

导入的

import * as cloneDeep from 'lodash/cloneDeep';是过滤器文本的字符串值。

this.searchString

树形结构由接口定义

  filter() {
    const clonedTreeLocal = cloneDeep(this.clonedTree);
    this.recursiveNodeEliminator(clonedTreeLocal);
    this.dataSource.data = clonedTreeLocal;
    this.treeControl.expandAll();
  }

实际过滤是通过功能export interface ITreeDataStructure { Id?: number; name: string; type: string; children?: Array<ITreeDataStructure>; }

完成的
recursiveNodeEliminator

答案 3 :(得分:1)

Stackblitz link for mat-tree filter

如果有人需要在不修改数据源的情况下直观地过滤 mat 树,那么请选择此解决方案。

基本上这个想法是隐藏不属于搜索字符串的节点。

输入框

<input [(ngModel)]="searchString" />

为叶子节点调用过滤函数(这是在第一个 mat-tree-node 中完成的)

<mat-tree-node
   *matTreeNodeDef="let node"
   [style.display]="
      filterLeafNode(node) ? 'none' : 'block'
   "
   .....
   ......

为叶子节点以外的节点调用过滤函数(这在第二个 mat-tree-node 中完成)

<mat-tree-node
   *matTreeNodeDef="let node; when: hasChild"
   [style.display]="filterParentNode(node) ? 'none' : 'block'"
   .....
   .....

filterLeafNode 函数

filterLeafNode(node: TodoItemFlatNode): boolean {
   if (!this.searchString) {
     return false
   }
   return node.item.toLowerCase()
     .indexOf(this.searchString?.toLowerCase()) === -1
}

filterParentNode 函数

filterParentNode(node: TodoItemFlatNode): boolean {

  if (    
    !this.searchString ||
    node.item.toLowerCase()
     .indexOf(
       this.searchString?.toLowerCase()
     ) !== -1
  ) {
    return false
  }
  const descendants = this.treeControl.getDescendants(node)

  if (
    descendants.some(
      (descendantNode) =>
        descendantNode.item
          .toLowerCase()
          .indexOf(this.searchString?.toLowerCase()) !== -1
    )
  ) {
    return false
  }
  return true
}

答案 4 :(得分:0)

首先在视图中添加输入作为过滤器。将keyup事件绑定到rxjs Subject

<input type="text" matInput placeholder="search" #filter (keyup)="keyEvent.next($event)" [(ngModel)]="keyword">

然后查询您的后端以使用关键字过滤树节点

this.keyEvent.pipe(
  map((e: any) => e.target.value.toLowerCase()),
  debounceTime(500),
  distinctUntilChanged(),
  switchMap((keyword: string) => {
    if (keyword && keyword.length > 2) {
      return this.yourservice.searchForData(this.entId, keyword);
    } else {
      return of();
    }
  })
)
.subscribe((r) => {
  this.nestedDataSource.data = r;
  this.nestedTreeControl.dataNodes = r;
  this.nestedTreeControl.expandAll();
});

答案 5 :(得分:0)

这是用于模型过滤器。创建 2 个列表,一个用于存储您的所有数据,另一个用作数据源。

 SearchCategory(searchText){
      this.searchText=searchText;
      this.categories=this.categoryNameSearch(this.AllCategories,searchText)
      this.dataSource.data = this.categories;
    }
    categoryNameSearch(categorys:Category[],searchText):Category[]{
      let category:Category[];
      category=categorys.filter(f=>this.converter(f.name).includes(this.converter(searchText)))
      categorys.forEach(element => {
        this.categoryNameSearch(element.childrens,searchText).forEach(e=>category.push(e))
      });
      return category;
    }
    converter(text) {
      var trMap = {
          'çÇ':'c',
          'ğĞ':'g',
          'şŞ':'s',
          'üÜ':'u',
          'ıİ':'i',
          'öÖ':'o'
      };
      for(var key in trMap) {
          text = text.replace(new RegExp('['+key+']','g'), trMap[key]);
      }
      return  text.replace(/[^-a-zA-Z0-9\s]+/ig, '') // remove non-alphanumeric chars
                  .replace(/\s/gi, "-") // convert spaces to dashes
                  .replace(/[-]+/gi, "-") // trim repeated dashes
                  .toLowerCase();
    
    }

HTML 端

  <input type="text" (ngModelChange)="SearchCategory($event)" placeholder="Search Category" class="form-control"/>