简体   繁体   English

定制管道产品过滤器?

[英]Custom Pipe product filter?

So what I'm trying to achieve is being able to toggle multiple filters on an NgFor with it updating each time a filter is toggled on or off.所以我想要实现的是能够在 NgFor 上切换多个过滤器,每次打开或关闭过滤器时它都会更新。

I have this pipe:我有这个管道:

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;
        });
    }
}

In my app.module.ts I have (Reduced for brevity):在我的 app.module.ts 我有(为简洁起见减少):

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

@NgModule({
    declarations: [
        FilterProducts
    ]
})

In my product component I have:在我的产品组件中,我有:

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

constructor() { }

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

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

And then on my NgFor I have (Reduced for brevity):然后在我的 NgFor 我有(为简洁起见减少):

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

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

The way I have the template doing the filtering setup it has subsections of Price, Brand and Type.我让模板进行过滤设置的方式有价格、品牌和类型的小节。 Within these are some buttons that the user can click on such as price being 0-50 or 50-100 etc. Ideally I'd like these to be able to be applied at the same time.其中有一些用户可以点击的按钮,例如价格为 0-50 或 50-100 等。理想情况下,我希望这些按钮能够同时应用。 So 0-50 and 50-100 would be selected and the ngFor filtered appropriately.因此将选择 0-50 和 50-100 并适当过滤 ngFor。

Is anyone able to give me some advice on how to achieve this?有没有人能给我一些关于如何实现这一目标的建议? I've searched everywhere and can only find pipes based on search boxes or dropdowns.我到处搜索,只能根据搜索框或下拉列表找到管道。

EDIT编辑

I've now updated this to reflect the help given to me by @PierreDuc.我现在更新了这个以反映@PierreDuc 给我的帮助。 I'm now struggling to pass the relevant filters into filterArgs.我现在正在努力将相关过滤器传递给 filterArgs。

EDIT 2编辑 2

I have now updated this again to reflect the progress thanks to @PierreDuc.感谢@PierreDuc,我现在再次更新了这个以反映进展。 Currently the ngFor is not filtering to the brand name passed through a (click).目前 ngFor 没有过滤到通过(点击)传递的品牌名称。

Thanks in advance.提前致谢。

You state that your filterArgs is a string array.您声明您的filterArgs是一个字符串数组。 In that case you should change your filter to this:在这种情况下,您应该将过滤器更改为:

@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
        });
    }
}

You can call this like so:你可以这样称呼它:

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

This will return all products where their name is cup or tea .这将返回名称为cuptea所有产品。 Beware of case sensitivity if that applies to you如果这适用于您,请注意区分大小写

To filter on multiple properties, you better send a {field : values} object to the pipe:要过滤多个属性,最好将{field : values}对象发送到管道:

To use your comment:要使用您的评论:

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

Then use this in your pipe:然后在你的管道中使用它:

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

And your pipe changes to this:您的管道更改为:

@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;
        });
    }
}

For the price evaluation I suggest you build a different pipe, where you can give a max and min settings and compare that to the price of the product对于价格评估,我建议您构建不同的管道,您可以在其中给出最大和最小设置并将其与产品价格进行比较

update更新

As an update to your code, you should assign the class property, not a local variable in your constructor.作为对代码的更新,您应该在构造函数中分配类属性,而不是局部变量。 And the filterArds is an object, not an array. filterArds 是一个对象,而不是一个数组。 So no need to initialize it like you did:所以不需要像你一样初始化它:

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

constructor() { }

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM