简体   繁体   English

是否可以使用 PrimeNG DataTable 添加自定义过滤器功能?

[英]Is it possible to add custom filterfunction with PrimeNG DataTable?

Basicly all info is provided in the title.基本上所有信息都在标题中提供。

It seems to me that I am bound to the filterMatchModes that are available ( contains, in, equals, endsWith, startsWith).在我看来,我必须使用可用的 filterMatchModes(包含、in、equals、endsWith、startsWith)。 In my usecase my column field is an array, and no single value.在我的用例中,我的列字段是一个数组,没有单个值。

My specified column looks like this:我指定的列如下所示:

<p-column field="types" [filter]="true" header="{{'AIRPORTS.TYPES' | translate}}">
    <template let-airport="rowData" pTemplate="body">
        <span *ngFor="let type of airport.types; let isLast = last">
            {{('AIRPORTS.' + type) | translate}}{{isLast ? '' : ', '}}
        </span>
    </template>
    <template pTemplate="filter" let-col>
        <p-dropdown [options]="choices"
                    [style]="{'width':'100%'}"
                    (onChange)="airportsDataTable.filter($event.value,col.field,col.filterMatchMode)"
                    styleClass="ui-column-filter">
        </p-dropdown>
    </template>
</p-column>

I had a similar problem where I had to filter array column-data with multiple selectable filter-values (from a p-multiSelect , so the filter was an array too).我有一个类似的问题,我必须用多个可选择的过滤器值过滤数组列数据(来自p-multiSelect ,所以过滤器也是一个数组)。 I figured out a way to extend the available filterMatchModes with some help from the original source-code.我从原始源代码中找到了一种扩展可用 filterMatchModes 的方法。 Unfortunately I can't vouch for it being good practice, but hey, in the version I'm using (PrimeNG 4.1.2) it works.不幸的是,我不能保证这是一个好的做法,但是,在我使用的版本 (PrimeNG 4.1.2) 中,它可以工作。

You may have to adapt and tune your filter-function to your needs, but here is what my solution would look like in your case (with a p-dropdown ):您可能需要根据自己的需要调整和调整过滤器功能,但这是我的解决方案在您的情况下的样子(带有p-dropdown ):

  • in the view, export the DataTable into a template-reference-variable ( #dt )在视图中,将 DataTable 导出为模板引用变量 ( #dt )
  • make it accessible in the component via the @ViewChild -decorator通过@ViewChild -decorator 在组件中访问它
  • add your own filter-function directly to the DataTable's array of filters (in ngOnInit() )将您自己的过滤器函数直接添加到 DataTable 的过滤器数组中(在ngOnInit()

component.ts组件.ts

@Component({...})
export class DatatableComponent implements OnInit {
    ...
    @ViewChild('dt') dt: DataTable;
    ...
    ngOnInit() {
        this.dt.filterConstraints['inCollection'] = function inCollection(value: any[], filter: any): boolean {
            // value = array of data from the current row
            // filter = value from the filter that will be searched in the value-array

            if (filter === undefined || filter === null) {
                return true;
            }

            if (value === undefined || value === null || value.length === 0) {
                return false;
            }

            for (let i = 0; i < value.length; i++) {
                if (value[i].toLowerCase() === filter.toLowerCase()) {
                    return true;
                }
            }

            return false;
        }
    }
}

In your view you can now use the new filter-function by setting the filterMatchMode of the column to what you named it before:在您的视图中,您现在可以通过将列的 filterMatchMode 设置为您之前为其命名的内容来使用新的过滤器功能:

component.html组件.html

<p-dataTable #dt ...>
    ...
    <p-column field="types" filterMatchMode="inCollection" header="{{'AIRPORTS.TYPES' | translate}}">
        <template let-airport="rowData" pTemplate="body">
            <span *ngFor="let type of airport.types; let isLast = last">
                {{('AIRPORTS.' + type) | translate}}{{isLast ? '' : ', '}}
            </span>
        </template>
        <template pTemplate="filter" let-col>
            <p-dropdown [options]="choices"
                        [style]="{'width':'100%'}"
                        (onChange)="dt.filter($event.value,col.field,col.filterMatchMode)"
                        styleClass="ui-column-filter">
            </p-dropdown>
        </template>
    </p-column>
    ...
</p-dataTable>

All I did in the view was set the filterMatchMode , otherwise I copied your code.我在视图中所做的只是设置了filterMatchMode ,否则我复制了您的代码。 (I also renamed the template-reference to #dt to make it shorter and more readable) (我还将模板引用重命名为#dt以使其更短且更具可读性)
Hint: you don't need [filter]=true in this column, since the standard filter won't show when your column has a custom filter-template.提示:在此列中您不需要[filter]=true ,因为当您的列具有自定义过滤器模板时,标准过滤器不会显示。

As I mentioned, with a custom filter function like this you can for example implement filtering array-data with a p-multiSelect filter (nested loop in filter-function), search for substrings in array or whatever else you can think of.正如我提到的,使用这样的自定义过滤器函数,您可以例如使用p-multiSelect过滤器(过滤器函数中的嵌套循环)实现过滤数组数据,搜索数组中的子字符串或任何您能想到的。

As a simple workaround, you can directily change the FilterUtils:作为一个简单的解决方法,您可以直接更改 FilterUtils:

import { FilterUtils } from 'primeng/utils';

FilterUtils['filterTest'] = (value, filter) => value <= filter && value >= filter;

this.dt.filter(search, 'field', 'filterTest');

In this GitHub issue we see that they removed filterConstraints which could be used with prior PrimeNG versions to extend the filter functionality.这个 GitHub 问题中,我们看到他们删除了filterConstraints ,它可以与之前的PrimeNG版本一起使用以扩展过滤器功能。

So... if you're on PrimeNG version 9 like me you can use FilterUtils instead.所以...如果你是PrimeNG版本9像我一样,你可以使用FilterUtils代替。

import { FilterUtils } from 'primeng/utils';

/**
* Custom filter to be used with PrimeNG Table
* https://www.primefaces.org/primeng/showcase/#/table
* Once we upgrade to version 11, this can be improved with FilterService:
* https://www.primefaces.org/primeng/showcase/#/filterservice
*/
setupCustomTableFilter() {
    FilterUtils['customContains'] = function customContains(value: any, filter: any): boolean {
        if (filter === undefined || filter === null)
            return true;

        if (value === undefined || value === null || value.length === 0)
            return false;

        let searchStringParts = filter.toLowerCase().split(' ') as string[];

        let columnValue = value.toString().toLowerCase();

        //debugger;
        // Make sure that all string parts are contained\included in the column value...
        var isMatch = searchStringParts.every(p => columnValue.includes(p));

        return isMatch;
    }
}

Note that you need to import it from import { FilterUtils } from 'primeng/utils';请注意,您需要从import { FilterUtils } from 'primeng/utils';导入它import { FilterUtils } from 'primeng/utils';

To be able to use it everywhere you can define the code above inside your app.component.ts file for example.例如,为了能够在任何地方使用它,您可以在app.component.ts文件中定义上面的代码。

The latest version of PrimeNG which is 11 as of now has added a FilterService which makes it more straightforward to implement custom filters. PrimeNG 的最新版本是 11,现在已经添加了一个FilterService ,这使得实现自定义过滤器变得更加简单。

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

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