【问题标题】:How to create an Angular2 filter pipe that acts such as Angular1 filter?如何创建一个像 Angular 1 过滤器一样的 Angular 2 过滤器管道?
【发布时间】:2017-10-07 15:17:39
【问题描述】:

我正在开发一个 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">

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

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

您知道如何使用 Angular2 Pipe 达到同样的效果吗? 提前谢谢你。

【问题讨论】:

  • 我能问你我的问题有什么问题吗?

标签: angular filter pipe ngfor


【解决方案1】:

你可以这样做:

使用此方法或创建您自己的方法来提取深层(甚至不是深层属性):

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

  const replaced: string = path.replace(/\[(\w+)\]/g, '.$1').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

【讨论】:

  • 如何添加negate作为参数?
  • 只需将参数添加到transform 方法,并在模板中传递。
  • 那么,@smartmouse,你测试过我的答案了吗?
  • 我收藏了它,我会在几个小时内测试它。反正我不知道怎么加negate,因为你的源代码对我来说太难了。
  • @smartmouse 我刚刚添加了一个接受negate 参数的新插件。让我知道它是否运作良好。
【解决方案2】:

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

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

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

支持多个参数。

将每个param: 分开

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

【讨论】:

  • 您的 Plunker 不起作用(请参阅控制台)。无论如何,正如我看到的源代码一样,没有使用带有过滤器的嵌套属性。
  • @smartmouse - 现在看看。之前比较着急没来得及测试。
  • Plunker 现在可以工作,但正如我之前所说,您是按属性过滤,而不是按我在问题中提出的按属性过滤。
  • @smartmouse 很抱歉你的问题很不清楚。午休后我会整理一些东西。
  • 我能问你我的问题有什么问题吗?无论如何,谢谢你的时间,我会等......
猜你喜欢
  • 1970-01-01
  • 2020-07-26
  • 1970-01-01
  • 2017-11-29
  • 2017-05-19
  • 2017-03-27
  • 2018-02-02
  • 1970-01-01
相关资源
最近更新 更多