动格过滤管

Dynamic grid filter pipe

我有一个如下所示的通用网格

<table class="table">
    <thead>
        <tr role="row" class="headers-filters">
            <th *ngFor="let objGColumn of gridColumns; let idx=index;">
                <dt-column-header [(filter)]="grdFilters[objGColumn.propertyKey]"></dt-column-header>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr role="row" *ngFor="let objRC of recordList | filterColumn: grdFilters; let idx=index;">
            <td class="text-center" *ngFor="let objGColumn of gridColumns; let idx=index;">           
                <span [textContent]="objRC[objGColumn.propertyKey]"></span>
            </td>
        </tr>
    </tbody>
</table>

其中 gridColumns 将是显示列的数组。

dt-column-header 是一个包含搜索列文本框的组件。它有双向绑定 属性 过滤器,这将是网格中的过滤器

过滤器会像 grdFilters = {LastName: "123", FirstName: "456"}

我的烟斗是这样的。我参考了 https://www.code-sample.com/2018/07/angular-6-search-filter-pipe-table-by.html

@Pipe({
  name: 'filterColumn'
})
export class GrdFilterPipe implements PipeTransform {
  transform(items: any, filter: any, defaultFilter: boolean): any {
    if (!filter){
      return items;
    }

    if (!Array.isArray(items)){
      return items;
    }

    if (filter && Array.isArray(items)) {
      let filterKeys = Object.keys(filter);

      if (defaultFilter) {
        return items.filter(item =>
            filterKeys.reduce((x, keyName) =>
                (x && new RegExp(filter[keyName], 'gi').test(item[keyName])) || filter[keyName] == "", true));
      }
      else {
        return items.filter(item => {
          return filterKeys.some((keyName) => {
            return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] == "";
          });
        });
      }
    }
  }
}

我的第一个问题是当 gridFilters 改变时管道没有调用。我不得不让它变得 不纯 这会影响性能。

另一个问题是管道在 {LastName: "123"}{FirstName: "456"}

下工作正常

但是无法使用 {LastName: "123", FirstName: "456"} OR {LastName: "", FirstName: "456"} OR {LastName: "123", FirstName: ""}

快速回答:

"My first issue is pipe is not calling when gridFilters change":

推荐: 将管道保留为纯管道并重新分配 gridFilters 而不是修改它。换句话说,不要在 dt-column-header 组件中使用 ngModel,而是使用输入事件并重新分配 gridFilters 变量。

或(不推荐): 通过在 @Pipe装饰师:

@Pipe({
  name: 'searchFilter',
  pure: false
})

请参阅此 StackBlitz DEMO 以及可用的示例代码。

"Another issue is pipe works fine with... But not working with":

问题出在管道的代码上:

return items.filter(item => {
  return filterKeys.some((keyName) => {
    return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] == "";
  });
});

显然您没有得到想要的结果。你没有提到你想要得到的结果的问题,你是什么意思 working/not working?根据您的需要编辑您的问题,我会更新我的答案。

详细解答

解释 pure/impure 管道:

您的管道是纯管道(在@Pipe 装饰器中不使用元数据pure: false 时的默认管道类型)。只有当原始输入值(字符串、数字、布尔值、符号)发生变化或对象引用(日期、数组、函数、对象)发生变化时,纯管道才会执行。

Angular Docs - Pure pipes

因此,您有 2 个选项作为解决方案:

方案一(推荐):

为了让您的管道在 gridFilters 更改时再次调用,您需要重新分配它而不是修改它。换句话说,不要在 dt-column-header 组件中使用 ngModel,而是使用输入事件并重新分配 gridFilters 变量。

方案二(不推荐):

通过在 @Pipe 装饰器中添加 pure: false 使您的管道成为 不纯管道 :

@Pipe({
  name: 'searchFilter',
  pure: false
})

这一次,您的管道将在每个组件更改检测周期中执行。 这也是不推荐此解决方案的原因,因为它会经常被调用,就像每次击键或鼠标移动一样频繁。

Angular Docs - Impure pipes 说:

With that concern in mind, implement an impure pipe with great care. An expensive, long-running pipe could destroy the user experience.