Angular - 过滤ngFor对象的数据数组

时间:2017-10-17 17:49:32

标签: angular

我有一个ngFor迭代一个对象数组。我在UI的表格中显示这些信息,一切正常。

我正在尝试实施一个小过滤器框,以便根据输入框中的内容缩小结果范围。

我正在使用pipe并使用了一组数据,但我不确定如何在不指定特定键的情况下搜索对象。我希望能够输入search term,如果它是任何一个对象中的值,请对其进行过滤。

管:

@Pipe({ name: 'filter' })
export class FilterPipe implements PipeTransform {
  public transform(values: any[], filter: string): any[] {
    if (!values || !values.length) return [];
    if (!filter) return values;

    return values.filter(v => v.indexOf(filter) >= 0);
  }
}

组件:

dataObj = [
  {
    name: 'Bob',
    age: 21,
    location: 'USA'
  },
  {
    name: 'Sally',
    age: 25,
    location: 'UK'
  }]

  filterString = '';

HTML:

<div>
  <h2>Hello {{name}}</h2>
  <input [(ngModel)]="filterString" />
  <div *ngFor="let d of (dataObj | filter: filterString)">
    {{ d.name }} - {{ d.age }} - {{ d.location }}
  </div>
</div>

期望的结果:

如果我输入21SallyUS,我希望看到结果。我试图避免将密钥硬编码到我搜索的管道中,因为我希望对象中的所有值都可以搜索。

这是一个plnkr示例:https://plnkr.co/edit/ubLyB152hgrPJSVp8xSB?p=preview

2 个答案:

答案 0 :(得分:3)

您可以通过Object.keys(o)遍历所有对象键,并检查至少一个对象字段中是否存在匹配。

您还需要处理v[k]的类型,因为indexOf仅适用于字符串(和数组),而不适用于数字。

这样的事情应该可以胜任:

public transform(values: any[], filter: string): any[] {
    if (!values || !values.length) return [];
    if (!filter) return values;

    return values.filter(v => {
        let match = false;

        Object.keys(v).forEach(k => {
            if (typeof v[k] === 'string') {
                match = match || v[k].indexOf(filter) >= 0;
            } else {
                match = match || v[k] == filter; // == intentinally
            }
        });

        return match;
    });
}

以下是您的修补程序:https://plnkr.co/edit/JoJ8M6YoID2yU6ASGEXf?p=preview

答案 1 :(得分:0)

根据Angular文档,最推荐的是使用函数执行过滤,并避免在* ngFor中使用管道。在此功能中,您可以使用所需的资源对对象集合执行过滤,如上所述。

要确定与过滤器字段中输入的文本匹配的项,请使用一个搜索嵌套字段的组件,为此,我在npm中发布了要使用的组件(wngx-filter)。

那样,您的代码可能如下所示:

对于此数据结构(可以使用复杂类型的对象引用或接口):

invoices: any[] = [
    {
      general: {
        number_invoice: "996"
      },
      note_invoice: "0001",
      state_invoice: "pending",
      customer_invoice: "Johan Corrales",
      date_invoice: "2018-10-30",
      days_invoice: "30",
      expiration_invoice: "2018-11-30",
      payment_invoice: "Credit"
    }
]

1-将管道组件注入构造函数中,以供 功能。

constructor(private pipefilter: WfilterPipe) {}

2-创建一个将接收数据收集以执行的功能 过滤器。在此功能中,您可以定义想要的属性 根据以下示例用于过滤器:

filterFunction(collection: any[]): any[] {
  return this.pipefilter.transform(collection, [
    { field: "general.number_invoice", value: this.filterInvoice }, // nested property
    { field: "note_invoice", value: this.filterInvoice },
    { field: "customer_invoice", value: this.filterInvoice },
    { field: "payment_invoice", value: this.filterInvoice }
  ]); 
}

请注意,“ general.number_invoice”属性是嵌套的,即在复杂类型内。 wngx-filter组件可以获取无限子级别的数据(嵌套)。

并像这样在html中使用此功能:

<li *ngFor="let invoice of filterFunction(invoices)">
...
</li>

作为组件用法的完整说明,您可以访问stackblitz并查看其代码,因为它很简单。