在PrimeNG:Datatable的过滤器之间应用自定义

时间:2018-03-12 07:20:52

标签: angular primeng primeng-datatable

考虑我在p-dataTable列中显示START和END YEAR的情况。

以下是列代码段:

<p-column field="startYear" header="Active Period" filterPlaceholder="Search" [filter]="true">
  <ng-template let-col let-manual="rowData" pTemplate="body">
    {{record.startYear}} - {{record.endYear}}
  </ng-template>
</p-column>

显示为:

|--------------|
| ActivePeriod |
|--------------|
|2015 - 2017   |
|--------------|
|2012 - 2016   |
|--------------|
|2023 - 2025   |
|--------------|
|2024 - 2030   |
|--------------|
|2011 - 2013   |
|--------------|

我想应用自定义过滤器,以便当用户在YEAR中键入时,表格应仅显示属于该活动期间的记录。

这意味着我必须编写一个逻辑,我检查用户是否在每个活动期间搜索年份。

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:1)

首先,您可以添加隐藏的助手字段years,其中包含一个年龄在给定范围内的数组,因此对于范围2012 - 2015,我们将得到一个数组:

[
  2012,
  2013,
  2014,
  2015
]

您可以使用map功能执行此操作,例如:

const yearsRange = row.endYear - row.startYear + 1;
YOUR_DATA_ARRAY.map(row => ({
  ...row,
  years: [...Array(yearsRange).keys()].map(y => y + row.startYear)
}))

开箱即用PRIME NG没有between过滤器。 Filters available currently是:

  • startsWith
  • 包含
  • 的endsWith
  • 等于
  • notEquals
  • LT
  • GT

您可以编写自己的过滤器来扩展它:

// import Table class
import { Table } from 'primeng/components/table/table';

.....

// get reference to your table
@ViewChild('dt') tableRef: Table;

.....

// extend filters
this.tableRef.filterConstraints.between = (value, filter: any): boolean => {
  if (filter === undefined || filter === null || filter === '') {
    return true;
  }

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

  return value.some(val => +val === +filter);
};

现在您可以在HTML中使用它了:

<p-table #dt [value]="cars">

  .....

  <input size="4"
         (input)="dt.filter($event.target.value, 'years', 'between')">

  .....

STACKBLITZ:https://stackblitz.com/edit/angular-sfoh3j?file=app%2Fapp.component.ts

<强>更新

我注意到你使用旧的(并且已弃用)DataTable, 解决方案应该非常相似,filters几乎与ltgt相同。只需在我的示例中更改导入和类型名称中的名称。 HTML语法也不同。 如果您需要旧版DataTable

的帮助,请与我们联系

答案 1 :(得分:1)

Andriy的回答帮助我解决了我在使用DataTable时遇到的一个特殊问题。对于浮点数,我们需要为&gt; =和&lt; =设置几个自定义过滤器。我采用了Andriy的解决方案并将其应用于我们的问题。我在这里发布代码,以防其他任何人从合并后的回复中受益。

1 - 构建了一个自定义组件来处理来自用户的输入

打字稿:

import { Component, Output, EventEmitter  } from '@angular/core';
import { FormBuilder, FormGroup, AbstractControl, FormControl } from '@angular/forms';
import { SelectItem } from 'primeng/components/common/selectitem';
import { ICustomGtLsFilter } from '../../Models/ICustomGtLsFilter';

@Component({
  selector: 'app-custom-filter',
  templateUrl: './custom-filter.component.html',
  styleUrls: ['./custom-filter.component.css']
})
export class CustomFilterComponent {
    @Output() onCriteriaSelectedChanged = new EventEmitter<ICustomGtLsFilter>();

    _myForm: FormGroup;
    _criteria: SelectItem[] = [{label: 'None', value: 'none'}, { label: '<=', value: 'lte' }, { label: '>=', value: 'gte' }];

    private _filterModel: ICustomGtLsFilter = new ICustomGtLsFilter();

    constructor(private _fb: FormBuilder) {
        this._myForm = _fb.group({
            _inputField: [null],
            _criteriaSel:[]
        });
    }

    fieldChanged(event) {
        // clear the input field
        if (event === "none") {
            this._myForm.controls['_inputField'].setValue('');
        }

        this._filterModel.Criteria = event;
        this._filterModel.FilterVal = this._myForm.controls['_inputField'].value;

        this.onCriteriaSelectedChanged.emit(this._filterModel);
    }
}

模板

<form [formGroup]="_myForm">
    <div class="row">
        <div class="col-sm-12">
            <input type="number" name="_inputField" id="_inputField" [formControl]="_myForm.controls['_inputField']" autocomplete="off" />
            <p-dropdown [options]="_criteria"
                        [autoWidth]="false"
                        id="_criteriaSel"
                        name="_criteriaSel"
                        placeholder="None"
                        formControlName="_criteriaSel"
                        (onChange)="fieldChanged($event.value)">
            </p-dropdown>
        </div>
    </div>
</form>  

接口:

export class ICustomGtLsFilter {
    FilterVal: number;
    Criteria: string;
}

以下是为我们要将过滤器应用于的列定义为ng-template的自定义组件:

<p-column field='TimeRem'
                  header='Time Remaining'
                  [sortable]='true'
                  [filter]='true'>
            <ng-template let-col
                         pTemplate='filter'>
                <app-custom-filter appendTo="body" 
                         (onCriteriaSelectedChanged)="dt.filter($event.FilterVal,col.field,$event.Criteria)">
                </app-custom-filter>
            </ng-template>
            <ng-template let-col
                         let-rd='rowData'
                         pTemplate='body'>
                <span appAlignRightStyle>{{rd[col.field] | format: '0.0'}}</span>
            </ng-template>
        </p-column>

最后使用DataTable的组件中的相关打字稿代码:

...

import { Component, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
import { CustomFilterComponent } from '../../../../shared/custom-filter/custom-filter.component';
import { ICustomGtLsFilter } from '../../../../Models/ICustomGtLsFilter';

export class SomeComponent implements OnInit {
    @ViewChild('dt') dt: DataTable;

 ngAfterViewInit() { 
        // custom filter implementations
        this.dt.filterConstraints['gte'] = function gte(value: any, filter: any): boolean {

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

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

            if (value >= filter) {
                return true;
            }

            return false;
        };

        this.dt.filterConstraints['lte'] = function lte(value: any, filter: any): boolean {

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

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

            if (value <= filter) {
                return true;
            }

            return false;
        };

        this.dt.filterConstraints['none'] = function none(value: any, filter: any): boolean {

            return true;
        };

    }