【问题标题】:Number filter custom comparator数字过滤器自定义比较器
【发布时间】:2017-11-19 00:56:27
【问题描述】:

简而言之:有没有办法为数字列过滤器实现自定义比较器?

长篇大论:

我在 Angular (2) 中使用 ag-grid。我为我的 ag-grid 中的单元格提供了我自己的组件:

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”。

那么,有没有办法为数字列过滤器实现自定义比较器?或者,如果没有,在这种情况下,我可以通过其他任何方式正确地从我的单元格中获取值吗?

【问题讨论】:

    标签: ag-grid ag-grid-ng2


    【解决方案1】:

    我最终做的是实现ag-grid custom filter component

    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
    }
    

    【讨论】:

    • 这正是我过去 2 天一直在寻找的,效果很好。我所做的唯一更改是包含一个响应式表单来消除输入抖动,因为在使用此组件作为过滤器时,debounceMs 键在列定义中不起作用。
    猜你喜欢
    • 2016-02-23
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 2016-10-20
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多