如何创建一个像 Angular1 过滤器一样的 Angular2 过滤器管道?

How to create an Angular2 filter pipe that acts such as Angular1 filter?

我正在开发一个 Angular2 应用程序,我需要为我的一些 *ngFor 指令使用过滤器。

我创建了以下 Pipe

import {Pipe, PipeTransform} from "@angular/core";

@Pipe({
    name: 'filter',
    pure: false
})
export class FilterPipe implements PipeTransform {
    transform(array: Array<Object>, key: string, value: string, negate: boolean): Array<Object> {
        if (array === null || array === undefined) {
            return [];
        } else {
            if (negate) {
                return array.filter(item => item[key] !== value);
            } else {
                return array.filter(item => item[key] === value);
            }
        }
    }
}

这是我如何使用它的示例:

<div class="item" *ngFor="let i of items | filter:'type':'S':true">

但是如果我要过滤 child 属性,它就不起作用了。 使用 Angular v1.x 我可以应用以下过滤器:

item in array | filter: { type: {subtype: 'foo'}}

你知道我怎样才能用我的 Angular2 管道达到同样的效果吗? 提前谢谢你。

这是一个有效的 Plunkr 实现您的过滤器管道

您只需确保使用正确的模板语法。

<span *ngFor="let item of items | filter:'key':'value'">
      {{item}}
</span>

支持多个参数。

将每个 param:

分开
{{ myData | myPipe: arg1:arg2:arg3... }}

你可以这样做:

使用这个或创建你自己的方法来提取深层(甚至不深层的属性):

getProperty(obj: any, path: string): string { 
  if (obj == null || obj.constructor !== Object) {
    return undefined;
  }

  const replaced: string = path.replace(/\[(\w+)\]/g, '.').replace(/^\./, '');
  const keys: string[] = replaced.split('.');
  let result: string = obj[keys.shift()];

  for (const key of keys) {
    if (result == null || result.constructor !== Object) {
      return undefined;
    }

    result = result[key];
  }

  return result;
}

现在,您将管道调整为:

@Pipe({
  name: 'filterBy',
  pure: false
})
export class FilterByPipe implements PipeTransform {

  transform(items: any[], prop: string, term: string, exact: boolean = false): any[] {

    if (!Array.isArray(items) || typeof term !== 'string') {
      return items;
    }

    const strTerm: string = `${term}`.toLowerCase();

    return items.filter((obj: any) => {
      const value: string = this.getProperty(obj, prop);
      if (!value) {
        return false;
      }

      const strValue: string = `${value}`.toLowerCase();  
      return exact
          ? strTerm === strValue
          : strValue.indexOf(strTerm) !== -1;
    });
  }

使用方法:

<div *ngFor="let item of items | filterBy: 'nestedObj.key': search: exact">

<div *ngFor="let item of items | filterBy: 'nestedObj[key]': search: exact">

DEMO

更新#1:

根据OP的要求,有一个版本接受另一个参数(negate):

<div *ngFor="let item of items | filterBy: 'nestedObj.key': search: exact: negate">

<div *ngFor="let item of items | filterBy: 'nestedObj[key]': search: exact: negate">

DEMO


PS: 请注意 exactnegate 是可选的,如果它们不存在,它们将自动成为 false.