Пользовательский компаратор числового фильтра

Вкратце: есть ли способ реализовать собственный компаратор для фильтров числовых столбцов?

Длинная история:

Я использую ag-grid в Angular (2). Я предоставляю свои собственные компоненты для ячеек в моей ag-сетке:

let column = {
  headerName: column.header,
  field: column.id,
  cellRendererFramework: DynamicComponent,
  filter: this.convertFormatToFilterType(column.format) // returns "text", "number" or "date"
}

Чтобы фильтры правильно получали значения из моих ячеек, я предоставляю настраиваемые компараторы (это для фильтров текстовых столбцов):

if (c.filter === "text")
  c['filterParams'] = {
    textCustomComparator: (filter, cell, filterText): boolean => {
    var filterTextLowerCase = filterText.toLowerCase();
    var valueLowerCase = cell.value.toString().toLowerCase();
    switch (filter) {
      case 'contains':
        return valueLowerCase.indexOf(filterTextLowerCase) >= 0;
      case 'notContains':
        return valueLowerCase.indexOf(filterTextLowerCase) === -1;
      case 'equals':
        return valueLowerCase === filterTextLowerCase;
      case 'notEqual':
        return valueLowerCase != filterTextLowerCase;
      case 'startsWith':
        return valueLowerCase.indexOf(filterTextLowerCase) === 0;
      case 'endsWith':
        var index = valueLowerCase.lastIndexOf(filterTextLowerCase);
        return index >= 0 && index === (valueLowerCase.length - filterTextLowerCase.length);
      default:
        // should never happen
        console.warn('invalid filter type ' + filter);
          return false;
        }
      }
    };

Как видите, мне нужно получить доступ к значению ячейки, используя "cell.value". Код выше работает нормально.

У меня проблемы с предоставлением аналогичных функций для фильтров числовых столбцов - они, похоже, не используют какой-либо настраиваемый компаратор. Следовательно, что происходит, фильтр пытается получить доступ к значению ячейки напрямую вместо использования "cell.value".

Итак, есть ли способ реализовать собственный компаратор для фильтров числовых столбцов? Или, если нет, то каким-либо другим способом я могу правильно получить значение из моих ячеек в этом случае?


person Jakub Siuda    schedule 16.06.2017    source источник


Ответы (1)


В итоге я реализовал ag-grid компонент настраиваемого фильтра

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

import { IFilterParams, IDoesFilterPassParams, RowNode, IAfterGuiAttachedParams } from 'ag-grid/main';
import { IFilterAngularComp } from 'ag-grid-angular/main';

// https://www.ag-grid.com/javascript-grid-filter-component/#gsc.tab=0 / Angular Filtering
// create your filter as a Angular component
@Component({
    selector: 'filter-cell',
    template: `
    <select #select (ngModelChange)="onSelectChange($event)" [ngModel]="operator">
      <option value="eq">Equals</option>
      <option value="neq">Not equal</option>
      <option value="lt">Less than</option>
      <option value="lte">Less than or equals</option>
      <option value="gt">Greater than</option>
      <option value="gte">Greater than or equals</option>
      <option value="inrange">In range</option>
    </select>

    <br>

    <input #input (ngModelChange)="onChange($event)" [ngModel]="text">
    <br>
    <div *ngIf='operator === "inrange"'>
      <input #input2 (ngModelChange)="onChange2($event)" [ngModel]="text2">
    </div>
    `,
    styles: ['select { margin: 2px 4px; }', 'input { height: 26px; margin: 2px 4px; }']
})
export class GridNumberFilterComponent implements IFilterAngularComp {
    private params: IFilterParams;
    private valueGetter: (rowNode: RowNode) => any;
    public operator: string = 'eq';
    public text: string = '';
    public text2: string = '';

    @ViewChild('select', { read: ViewContainerRef }) public select;
    @ViewChild('input', { read: ViewContainerRef }) public input;
    @ViewChild('input2', { read: ViewContainerRef }) public input2;

    agInit(params: IFilterParams): void {
        this.params = params;
        this.valueGetter = params.valueGetter;
    }

    isFilterActive(): boolean {
        return this.text !== null && this.text !== undefined && this.text !== '';
    }

    doesFilterPass(params: IDoesFilterPassParams): boolean {
        let cellNumber = Number(this.valueGetter(params.node).value);
        let filterNumber = this.text ? Number(this.text) : -Infinity;
        let filterNumber2 = this.text2 ? Number(this.text2) : Infinity;

        switch (this.operator) {
            case 'eq': return cellNumber === filterNumber;
            case 'neq': return cellNumber !== filterNumber;
            case 'lt': return cellNumber < filterNumber;
            case 'lte': return cellNumber <= filterNumber;
            case 'gt': return cellNumber > filterNumber;
            case 'gte': return cellNumber >= filterNumber;
            case 'inrange': return cellNumber >= filterNumber && cellNumber <= filterNumber2;

            default: return true;
        }
    }

    getModel(): any {
        return { value: this.text };
    }

    setModel(model: any): void {
        this.text = model ? model.value : '';
    }

    afterGuiAttached(params: IAfterGuiAttachedParams): void {
        this.input.element.nativeElement.focus();
    }

    componentMethod(message: string): void {
        alert(`Alert from PartialMatchFilterComponent ${message}`);
    }

    onSelectChange(newValue): void {
        if (this.operator !== newValue) {
            this.operator = newValue;
            this.params.filterChangedCallback();
        }
    }

    onChange(newValue): void {
        if (this.text !== newValue) {
            this.text = newValue;
            this.params.filterChangedCallback();
        }
    }

    onChange2(newValue): void {
        if (this.text2 !== newValue) {
            this.text2 = newValue;
            this.params.filterChangedCallback();
        }
    }
}

которые я добавляю в свою колонку следующим образом:

let column = {
  headerName: column.header,
  field: column.id,
  cellRendererFramework: DynamicComponent,
  filterFramework: GridNumberFilterComponent
}
person Jakub Siuda    schedule 16.06.2017
comment
Это именно то, что я искал последние 2 дня, работает неплохо. Единственное изменение, которое я сделал, - это включение реактивной формы для устранения ошибок ввода, поскольку клавиша debounceMs не работала в определении столбца при использовании этого компонента для фильтра. - person Qarun Qadir Bissoondial; 23.06.2021