AgGrid Select 单元格编辑器

AgGrid Select Cell Editor

我正在使用 v8 angular ag-grid。

this.columns = [
    {headerName: "XYZ", field:"XYZ", 
    editable: true ,cellEditor: "select", 
    cellEditorParams: {values : [// list of values]},
] 

我想创建一个下拉列表 select,只需单击一下键盘导航(在键盘上按下的字母应显示以该字母开头的值)。

您可以为此使用自动完成功能。首先,你需要准备自己的AutoComplete组件。

AutoCompleteComponent.ts

import { Component, AfterViewInit, ViewChild, ViewEncapsulation, ElementRef, HostListener } from '@angular/core';
import { ICellEditorAngularComp } from 'ag-grid-angular'; 

@Component({
  selector: 'auto-complete',
  encapsulation: ViewEncapsulation.None, 
  template: ` 
        <input #input
            [(ngModel)]="inputValue"
            (ngModelChange)="processDataInput($event)"  >
        <ag-grid-angular 
            [style.height]="gridHeight + 'px'"
            [style.max-width]="gridWidth + 'px'"
            class="ag-theme-balham"
            [rowData]="rowData" 
            [columnDefs]="columnDefs"
            [rowSelection]="rowSelection"
            (gridReady)="onGridReady($event)"
            [headerHeight]="headerHeight"
            (rowClicked)="rowClicked($event)">
        </ag-grid-angular>
    `
})
export class AutoCompleteComponent implements ICellEditorAngularComp, AfterViewInit {
  // variables for agGrid
  public params: any;
  public gridApi: any;
  public rowData: any;
  public columnDefs: [{}];
  public rowSelection: string = 'single';
  public columnFilter: any;
  // variables for component
  public returnObject: boolean;
  public cellValue: string;
  public filteredRowData: any;
  public inputValue: string;
  public apiEndpoint: string;
  public gridHeight: number = 175;
  public gridWidth: number = 375;
  public useApi: boolean;
  public propertyName: string;
  public isCanceled: boolean = true;
  public selectedObject: any = {}
  public headerHeight: number = 0;
  private cellFocusIndex: number;

  @ViewChild("input", { static: false }) input: ElementRef;
  showedColumn: any;

  constructor() { }


  // will be selected if there is a default value
  ngAfterViewInit() {
    window.setTimeout(() => {
      if (this.inputValue == this.cellValue) {
        this.input.nativeElement.select();
      } else {
        this.input.nativeElement.focus();
      }
      if (this.inputValue && !this.useApi) this.updateFilter();
    })
  }

  // ICellEditorAngularComp functions
  agInit(params: any): void {
    this.params = params;
    if (!params.rowData) {
      this.apiEndpoint = params.apiEndpoint;
      this.useApi = true;
      this.rowData = [{}]
    } else {
      this.rowData = params.rowData;
    }
    if (params.gridHeight) this.gridHeight = params.gridHeight;
    if (params.gridWidth) this.gridWidth = params.gridWidth;
    params.columnDefs.forEach((el: any) => {
      if (typeof el.filter === "undefined") {
        el.filter = 'agTextColumnFilter'
      }
    });
    this.columnDefs = params.columnDefs;
    this.propertyName = params.propertyRendered;
    this.showedColumn = params.showedColumn;
    this.cellValue = params.data[this.propertyName];
    this.returnObject = params.returnObject;

    if (!params.charPress) {
      if (this.cellValue) this.inputValue = this.cellValue;
    } else {
      this.inputValue = params.charPress;
    }
  }

  getValue(): any {
    if (!this.returnObject) return this.selectedObject[this.propertyName];
    return this.selectedObject;
  }
  isPopup(): boolean {
    return true;
  }
  isCancelAfterEnd(): boolean {
    return this.isCanceled
  }

  // ag-Grid functions
  onGridReady(params: any) {
    this.gridApi = params.api;
    this.gridApi.sizeColumnsToFit();
    this.columnFilter = this.gridApi.getFilterInstance(this.propertyName);
  }

  // component functions
  // double clicked value will be selected and combobox will be closed.
  rowClicked(params: any) {
    this.selectedObject = params.data;
    this.isCanceled = false;
    this.params.api.stopEditing();
  }


  // Board Event
  @HostListener('keydown', ['$event'])
  onKeydown(event: any) {
    event.stopPropagation();
    if (event.key == "Escape") {
      this.params.api.stopEditing();
      return false;
    }
    if (event.key == "Enter" || event.key == "Tab") {
      this.rowConfirmed();
      return false;
    }
    if (event.key == "ArrowUp") {
      this.navigateGrid();
      if (this.cellFocusIndex == 0 && this.gridApi.getFocusedCell().rowIndex == 0) { //-- yukarı çıkmak istiyor
        this.input.nativeElement.focus();
      } else {
        this.cellFocusIndex = this.gridApi.getFocusedCell().rowIndex;
      }
      return false;
    }
    if (event.key == "ArrowDown") {
      this.navigateGrid();
      return false;
    }
  }

  processDataInput(event: any) {
    this.updateFilter()
  }

  updateFilter() {
    this.columnFilter.setModel({
      type: 'contains',
      filter: this.inputValue,
    });
    this.columnFilter.onFilterChanged();
    if (this.gridApi.getDisplayedRowAtIndex(0)) {
      this.gridApi.getDisplayedRowAtIndex(0).setSelected(true);
      this.gridApi.ensureIndexVisible(0, 'top');
    } else {
      this.gridApi.deselectAll();
    } 
  }

  // Enter Event Process
  rowConfirmed() {
    if (this.gridApi.getSelectedRows()[0]) {
      this.selectedObject = this.gridApi.getSelectedRows()[0];
      this.isCanceled = false;
    }
    this.params.api.stopEditing();
  } 

  // Arrow change event
  // The data navigated on it is written to adjust its position on the screen with the arrow keys.
  navigateGrid() {
    if (this.gridApi.getFocusedCell() == null || this.gridApi.getDisplayedRowAtIndex(this.gridApi.getFocusedCell().rowIndex) == null) { // check if no cell has focus, or if focused cell is filtered
      this.gridApi.setFocusedCell(this.gridApi.getDisplayedRowAtIndex(0).rowIndex, this.showedColumn != undefined ? this.showedColumn : this.propertyName);
      this.gridApi.getDisplayedRowAtIndex(this.gridApi.getFocusedCell().rowIndex).setSelected(true);
    } else {
      this.gridApi.setFocusedCell(this.gridApi.getFocusedCell().rowIndex, this.showedColumn != undefined ? this.showedColumn : this.propertyName);
      this.gridApi.getDisplayedRowAtIndex(this.gridApi.getFocusedCell().rowIndex).setSelected(true);
    }
  }
}

新创建的组件必须在模块中定义

custom.module.ts

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AgGridModule} from 'ag-grid-angular';
import {AutoCompleteComponent} from './auto-complete.component';

@NgModule({
  declarations: [CustomComponent],
  imports: [CommonModule,
    AgGridModule.withComponents([AutoCompleteComponent])],
  exports: [],
  providers: []
})
export class CustomModule {
}

我们的新组件现在可以使用了

在custom.component.ts


  frameworkComponents: any = { 
    autoComplete: AutoCompleteComponent
  };

columnsDef = [
{
        headerName: 'XYZ,
        field: 'xyz',
        editable: true,
        filter: 'agSetColumnFilter',
        cellEditorSelector: function () {
          return {
            component: 'autoComplete',
            params: {
              propertyRendered: 'xyz',
              returnObject: true,
              showedColumn: 'xyz',
              rowData: [{xyz : '1',, desc : 'One'}, {xyz :'2', desc : 'Two'}, {xyz:'3', desc : 'Three'}],
              columnDefs: [
                {
                  headerName: 'XYZ',
                  field: 'xyz',
                  filter: 'agTextColumnFilter',
                  suppressMenu: true,
                  valueFormatter: (event: any) => {
                    let data = event.data
                    return data.xyz + " - " + data.desc
                  }
                },
                {
                  headerName: 'DESC',
                  field: 'desc',
                  filter: 'agTextColumnFilter',
                  hide: true
                }
              ]
            }
          }
        },
        comparator: this.customComparator,
        valueGetter: (event: any) => {
           const val = event.data.xyz;
            return val.xyz+ " - " + val.desc;
        }
      }]

在custom.component.html

<ag-grid-angular #agGrid (gridReady)="onGridReady($event)"
   (selectionChanged)="onSelectionChanged($event)" 
   [columnDefs]="columnDefs" 
   [frameworkComponents]="frameworkComponents"  
   [rowData]="rowData" 
   [suppressRowClickSelection]="true" 
   class="ag-theme-balham"  >
</ag-grid-angular>

请尝试 return。我在本地尝试时可以得到解决方案。

工作演示:https://stackblitz.com/edit/angular-ivy-ipvkac?file=src/app/app.component.ts

我能够通过创建单元格渲染器而不是编辑器来实现所需的效果 - 这帮助我通过单击获得下拉菜单并使用 angular material 实现了下拉菜单。