如何创建一个自定义管道,以角度4

时间:2017-07-25 05:10:02

标签: node.js angular typescript angular-cli

我正在努力应用一个接收对象作为过滤参数的管道。在这里,我让代码我正在处理:

import { IProductFilter } from 'app/helpers/filters';
import { IProduct } from './../../domain/product';
import { PipeTransform, Pipe } from '@angular/core'

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

    transform(value: IProduct[], filterBy: IProductFilter): IProduct[] {

        return value.filter((product: IProduct) => {
            return ((product.productName.toLocaleLowerCase().indexOf(filterBy.productName.toLocaleLowerCase()) !== -1 || product.productName) &&
                (product.productCode.toLocaleLowerCase().indexOf(filterBy.productCode.toLocaleLowerCase()) !== -1 || product.productCode) && 
                (product.releaseDate.toLocaleLowerCase().indexOf(filterBy.releaseDate.toLocaleLowerCase()) !== -1 || product.releaseDate) &&
                (product.price === filterBy.price || product.price) &&
                (product.starRating === filterBy.rating || product.starRating))
        });
    }
}

这是我的html模板

<tr *ngFor='let product of products | productFilter:productCriteria' (click)="viewDetails(product.productId)">
                        <td>
                            <label>{{ product.productName }}</label>
                        </td>
                        <td>
                            <label>{{ product.productCode }}</label>
                        </td>
                        <td>
                            <label>{{ product.releaseDate | date: 'dd/MM/yyyy' }}</label>
                        </td>
                        <td>
                            <label>{{ product.price | currency:'USD':true:'1.2-2' }}</label>
                        </td>
                        <td>
                            <label>{{ product.starRating }}</label>
                        </td>
                        <td>
                            <a md-button routerLink="." (click)='openModal(2, product)' role="button"><i class="fa fa-lg fa-pencil" aria-hidden="true" title="Edit"></i></a>
                            <a md-button routerLink="." (click)='removeProduct(product.productId)' role="button"><i class="fa fa-lg fa-times" aria-hidden="true" title="Remove"></i></a>
                        </td>
                    </tr>

这并不是要过滤我的列表。但是,如果我只应用我的界面的一个属性,过滤器就可以正常工作。

提前致谢!

1 个答案:

答案 0 :(得分:4)

根据此处的文档:https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

,建议不要使用管道进行过滤或排序

相反,请考虑在组件类中构建排序或过滤。

以下是一个例子:

import { Component, OnInit } from '@angular/core';

import { IProduct } from './product';
import { ProductService } from './product.service';

@Component({
    templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit {

    _listFilter: string;
    get listFilter(): string {
        return this._listFilter;
    }
    set listFilter(value: string) {
        this._listFilter = value;
        this.filteredProducts = this.listFilter ? this.performFilter(this.listFilter) : this.products;
    }

    filteredProducts: IProduct[];
    products: IProduct[] = [];

    constructor(private _productService: ProductService) {

    }

    performFilter(filterBy: string): IProduct[] {
        filterBy = filterBy.toLocaleLowerCase();
        return this.products.filter((product: IProduct) =>
              product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
    }

    ngOnInit(): void {
        this._productService.getProducts()
                .subscribe(products => {
                    this.products = products;
                    this.filteredProducts = this.products;
                },
                    error => this.errorMessage = <any>error);
    }
}

让我们来看看你的过滤逻辑:

return value.filter((product: IProduct) => {
    return ((product.productName.toLocaleLowerCase().indexOf(filterBy.productName.toLocaleLowerCase()) !== -1 || product.productName) &&
        (product.productCode.toLocaleLowerCase().indexOf(filterBy.productCode.toLocaleLowerCase()) !== -1 || product.productCode) && 
        (product.releaseDate.toLocaleLowerCase().indexOf(filterBy.releaseDate.toLocaleLowerCase()) !== -1 || product.releaseDate) &&
        (product.price === filterBy.price || product.price) &&
        (product.starRating === filterBy.rating || product.starRating))
});

以下每一行:

(product.productName.toLocaleLowerCase()
       .indexOf(filterBy.productName.toLocaleLowerCase()) !== -1 
   || product.productName)

基本上是说:

1)如果小写产品名称包含小写filterBy产品名称

中定义的字符

2)或者设置了productName

3)然后将产品包含在已过滤的列表中。

因此,只要设置了所有属性,它就会包含列表中的项目(而不是将其过滤掉)。

尝试这样的事情:

return value.filter((product: IProduct) => 
   (filterBy.productName ?
    product.productName.toLocaleLowerCase().indexOf(filterBy.productName.toLocaleLowerCase()) !== -1 :
    true) &&
   (filterBy.productCode ?
    product.productCode.toLocaleLowerCase().indexOf(filterBy.productCode.toLocaleLowerCase()) !== -1 :
    true) && ...