AgGrid 选择单元格编辑器

Posted

技术标签:

【中文标题】AgGrid 选择单元格编辑器【英文标题】:AgGrid Select Cell Editor 【发布时间】:2021-08-09 08:53:19 【问题描述】:

我正在使用 v8 角度 ag-grid。

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

我想通过单击键盘导航来创建一个下拉选择(键盘上按下的字母应显示以该字母开头的值)。

【问题讨论】:

【参考方案1】:

您可以为此使用自动完成功能。首先,您需要准备自己的 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>

请尝试返回。当我在本地尝试时,我可以得到解决方案。

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

【讨论】:

你在 plunker 或 stackblitz 上有这个例子吗? stackblitz.com/edit/angular-ivy-ipvkac?file=src/app/… 这个例子运行失败 是的,它正在工作,但所需的功能是键盘导航。单元格以按字符开始渲染下拉选项,然后单击编辑即可开始(意味着单击时出现下拉菜单)【参考方案2】:

我能够通过创建单元格渲染器而不是编辑器来实现所需 - 这有助于我通过单击获得下拉菜单并使用角度材料实现下拉菜单。

【讨论】:

您能分享一下您的解决方案吗?

以上是关于AgGrid 选择单元格编辑器的主要内容,如果未能解决你的问题,请参考以下文章

ag-grid实现全行编辑

UITableView 在进入编辑模式时取消选择单元格

tableview 编辑模式单元格选择复选标记在滚动时消失

如何使 JTable 单元格不可编辑但应该能够选择和复制当前单元格中的值

ExtJS 4.1 - 编辑单元格时消失的选择(组合框编辑器)

excel锁定单元格不允许编辑(excel锁定单元格不能修改)