定制管道产品过滤器?

问题描述:

所以我试图实现的是能够在NgFor上切换多个过滤器,并在每次过滤器打开或关闭时进行更新。定制管道产品过滤器?

我有这样的管道:

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

@Pipe({ 
    name: 'filterProducts' 
}) 
export class FilterProducts implements PipeTransform { 
    transform(products: any[], args: {[field : string] : string[]}): any[] { 
     if (!products) return []; 
     if (!args) return products; 

     return products.filter((pr: any) => { 

      for(let field in args) { 

       if(args[field ].indexOf(pr[field]) === -1) { 
        return false; 
       } 
      } 

      return true; 
     }); 
    } 
} 

在我app.module.ts我已经(精简为简洁起见):

import { FilterProducts } from '../pages/products/productsFilter.pipe'; 

@NgModule({ 
    declarations: [ 
     FilterProducts 
    ] 
}) 

在我的产品组件,我有:

public filterArgs : {[field : string] : string[]} = {}; 

constructor() { } 

addBrandFilter(brands: string[]) { 
    this.addFilter('brand', brands); 
} 

addFilter(field: string, values: string[]): void { 
    this.filterArgs[field] = values; 
} 

然后在我的NgFor我有(减少简洁):

*ngFor="let product of products | filterProducts: filterArgs;" 

<li class="search-filters__item" (click)="addBrandFilter(['Brand Name'])">Brand Name</li> 

我使用模板进行筛选设置的方式,它包含价格,品牌和类型子部分。其中有一些按钮,用户可以点击,如价格为0-50或50-100等。理想情况下,我希望这些能够同时应用。所以选择0-50和50-100并且适当地过滤ngFor。

任何人都可以给我一些建议,如何实现这一目标?我到处搜索,只能根据搜索框或下拉菜单找到管道。

编辑

我现在已经更新了这个以反映@PierreDuc给我的帮助。我现在正努力将相关过滤器传递到filterArgs。

EDIT 2

现在我已经再次更新这反映进度感谢@PierreDuc。目前,ngFor不会过滤通过(点击)传递的品牌名称。

在此先感谢。

你声明你的filterArgs是一个字符串数组。在这种情况下,你应该你的过滤器改成这样:

@Pipe({ 
    name: 'filterProducts' 
}) 
export class FilterProducts implements PipeTransform { 
    transform(products: any[], field : string, value : string[]): any[] { 
     if (!products) return []; 
     if (!value) return products;  
     return products.filter((pr: any) => { 
      return value.indexOf(pr[field]) > -1 
     }); 
    } 
} 

您可以致电此像这样:

*ngFor="let product of products | filterProducts: 'name' : ['cup', 'tea']" 

这将返回所有的产品,他们的名字是cuptea。小心区分大小写的,如果适用于您

要过滤的多个属性,你最好派一个{field : values}对象管道:

要使用您的评论:

let filterArgs : {[field : string] : string[]} = { 
    name : ['brand', 'otherbrand'], 
    type : ['A', 'B'] 
}; 

中然后用这个你管:

*ngFor="let product of products | filterProducts: filterArgs" 

和你管更改为:

@Pipe({ 
    name: 'filterProducts' 
}) 
export class FilterProducts implements PipeTransform { 
    transform(products: any[], args: {[field : string] : string[]}): any[] { 
     if (!products) return []; 
     if (!args) return products;  
     return products.filter((pr: any) => { 
      for(let field in args) { 
       if(args[field ].indexOf(pr[field]) === -1) { 
        return false; 
       } 
      } 
      return true; 
     }); 
    } 
} 

对于价格的评估,我建议你建立一个不同的管道,在那里你可以给一个最大值和最小值的设置和比较,为产品

更新

的价格作为更新你的代码,你应该分配类属性,而不是你的构造函数中的局部变量。 filterArds是一个对象,而不是一个数组。所以不需要像你这样初始化它:

public filterArgs : {[field : string] : string[]} = {}; 

constructor() { } 

addBrandFilter(brands: string[]) { 
    this.addFilter('brand', brands); 
} 

addFilter(field: string, values: string[]): void { 
    this.filterArgs[field] = values; 
} 
+0

谢谢你,这已经很好地工作了。我如何将它转换为能够从一组过滤器中单击以过滤ngFor?假设我希望看到价格在0到50英镑之间的产品,名称是“Brand”,并且是“TypeA”? (对不起,如果没有意义)。 – Alsh

+0

我已经更新了我的答案,但未经测试的代码:) – PierreDuc

+0

非常感谢,我已经实现了这一点,但是当我尝试运行addBrandFilter函数时,我现在收到错误“Can not read property name'of undefined”更新的代码)。有任何想法吗? :) – Alsh