问题描述
我使用的是 v8 angular ag-grid。
this.columns = [
{headerName: "XYZ",field:"XYZ",editable: true,cellEditor: "select",cellEditorParams: {values : [// list of values]},]
我想通过单击鼠标和键盘导航来创建下拉选择(按下键盘上的字母应显示以该字母开头的值)。
解决方法
您可以为此使用自动完成功能。首先,您需要准备自己的 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',filter: 'agTextColumnFilter',suppressMenu: true,valueFormatter: (event: any) => {
let data = event.data
return data.xyz + " - " + data.desc
}
},{
headerName: 'DESC',field: 'desc',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