动态网格过滤管

时间:2018-12-21 10:27:20

标签: angular filter pipe angular-filters angular-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"}{LastName: "", FirstName: "456"}{LastName: "123", FirstName: ""}

1 个答案:

答案 0 :(得分:1)

快速解答:

“我的第一个问题是gridFilters更改时管道未调用”:

推荐:将管道保留为纯管道,然后重新分配gridFilters而不是对其进行修改。换句话说,不要在您的dt-column-header组件中使用ngModel,而要使用input事件并重新分配gridFilters变量。

或(不推荐):通过在pure: false装饰器中添加@Pipe,使管道成为不纯管道

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

请参见此StackBlitz DEMO并提供有效的示例代码。

“另一个问题是管道可以与...配合使用,但不能与之配合使用”:

问题出在管道的代码上

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

显然您没有获得想要的结果。您没有提到要获得的结果的问题,这意味着工作/不工作?根据需要修改问题,我将更新答案。

详细答案

解释纯/不纯管道:

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

Angular Docs - Pure pipes

因此,您有2个解决方案:

解决方案1(推荐)

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

解决方案2(不推荐)

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

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

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

Angular Docs - Impure pipes说:

  

请牢记这一点,小心安装不纯净的管道。昂贵的,长期运行的管道可能会破坏用户体验。