web-dev-qa-db-ja.com

mat-treeコンポーネントをフィルタリングする方法Angular Material 6.0.1

Mat-tree angular materialコンポーネントを使用しています。これは、複数選択、すべて展開/すべて折りたたむなど、非常に便利な機能を備えたNiceコンポーネントです。ツリーフィルタリングは見つかりませんでした。 APIのいずれかの機能:マットツリーフィルターを取得するために、この機能に遭遇した人や回避策を実行した人はいますか。

enter image description here

8
SatAj

新しいデータソースを作成することで問題を解決しました(フィルター処理済み)。

stackblitzサンプル

共有リンクの例を説明します:ChecklistDatabasefilter(filterText: string)でデータをフィルタリングし、dataChangeイベントをトリガーしました。その後、datasource.dataは、TreeChecklistExampleで処理されたイベントによって変更されました。したがって、データソースが変更されました。

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

同じタスクに数日間費やした後、ここで私が与えることができるいくつかのヒントがあります:入力イベントを使用してユーザー入力を追跡しています:

<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で実行できる検索の実行を遅らせたいと思います。

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

検索を実行するには、cssクラスを使用してノードを非表示および表示します。これはプレゼンテーションコレクションで直接行われ、フラットで非常に簡単にフィルター処理できます。

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私の場合)選択を失うか、プレゼンテーションにマップし直す必要があるため。ここに私の初期データがあります:

this.treeFlattener = new MatTreeFlattener(
  this.transformer, this._getLevel, this._isExpandable, this._getChildren
);
this.treeControl = new FlatTreeControl<SkillFlatNode>(
  this._getLevel, this._isExpandable
);
this.dataSource = new MatTreeFlatDataSource(
  this.treeControl, this.treeFlattener
);

skillService.dataChange.subscribe(data => {
  this.dataSource.data = data;
});
4
ganelon

単純な再帰を使用してツリーをフィルター処理できます。以下にコードスニペットを示します。

filter()関数は、(keyup)input type="text"で呼び出されます。 cloneDeep関数はlodashからインポートされます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によって行われます

recursiveNodeEliminator(tree: Array<ITreeDataStructure>): boolean {
    for (let index = tree.length - 1; index >= 0; index--) {
      const node = tree[index];
      if (node.children) {
        const parentCanBeEliminated = this.recursiveNodeEliminator(node.children);
        if (parentCanBeEliminated) {
          if (node.name.toLocaleLowerCase().indexOf(this.searchString.toLocaleLowerCase()) === -1) {
            tree.splice(index, 1);
          }
        }
      } else {
        // Its a leaf node. No more branches.
        if (node.name.toLocaleLowerCase().indexOf(this.searchString.toLocaleLowerCase()) === -1) {
          tree.splice(index, 1);
        }
      }
    }
    return tree.length === 0;
  }
1
Karthik

まず、ビューにフィルターとして入力を追加します。キーアップイベントを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();
});
0
steamfood