我正在我的angular 7应用程序中实现ag-grid的单元格编辑功能。我需要显示其中一个单元格的下拉值。我在cellEditorParams中设置下拉列表的值。我可以看到值已经绑定,但没有显示下拉列表。有人可以告诉我这里是什么问题
cellEditorParams: {
values: this.DocumentUploadDetails.DocumentTypes,
cellRenderer: (params) => params.value.Name
}
我怀疑问题在于此行 cellRenderer:(参数)=> params.value.Name
我实现了以下用于单元格编辑的事件
onCellClicked($event){
// check whether the current row is already opened in edit or not
if(this.editingRowIndex != $event.rowIndex) {
console.log($event);
$event.api.startEditingCell({
rowIndex: $event.rowIndex,
colKey: $event.column.colId
});
this.editingRowIndex = $event.rowIndex;
}
}
JSON
DocumentTypes is basically collection of Id and Name properties
[{"Id":4,"Name":"DD Questionnaires / Materials"},{"Id":6,"Name":"Constitutional Documents"},{"Id":7,"Name":"Regulation / References"},{"Id":8,"Name":"Email Correspondence"},{"Id":10,"Name":"Manager Letters"},{"Id":13,"Name":"Office Maps"},{"Id":14,"Name":"Quantitative"},{"Id":1,"Name":"Fund"},{"Id":20,"Name":"Other"},{"Id":21,"Name":"Fund DD Visit"},{"Id":23,"Name":"Investment Proposal"},{"Id":22,"Name":"Research Note"},{"Id":102,"Name":"Fund Organizational Document - Articles of Association"},{"Id":104,"Name":"Form ADV - Part 1"},{"Id":105,"Name":"Due Diligence Questionnaire"},{"Id":106,"Name":"Financial Statements"},{"Id":107,"Name":"Fund Organizational Document - Limited Partnership Agreement"},{"Id":108,"Name":"Investment Management Agreement"},{"Id":109,"Name":"Marketing Presentation"},{"Id":110,"Name":"Third Party Research - Morningstar Report"},{"Id":111,"Name":"Newsletter"},{"Id":112,"Name":"Offering Circular"},{"Id":113,"Name":"Side Letter"},{"Id":114,"Name":"Risk Exposure"},{"Id":115,"Name":"Redemption Form"},{"Id":116,"Name":"Offering Circular - Supplement"},{"Id":117,"Name":"Subscription Form - Additional Subscription"},{"Id":118,"Name":"Subscription Form - Non US Investor"},{"Id":119,"Name":"Subscription Form - US Tax Exempt"},{"Id":120,"Name":"Subscription Form - US Investor"},{"Id":123,"Name":"Termination Letter"},{"Id":125,"Name":"Corporate Communications"},{"Id":126,"Name":"Articles - News"},{"Id":127,"Name":"Detailed AUM"},{"Id":128,"Name":"Cube Risk Document"},{"Id":132,"Name":"Valuation Memo"},{"Id":133,"Name":"SEC 13F"},{"Id":134,"Name":"NAV Statements"},{"Id":135,"Name":"Corporate Action"},{"Id":137,"Name":"Form ADV - Part 2"},{"Id":138,"Name":"Third Party Research - Other"},{"Id":141,"Name":"Factor Analysis"},{"Id":142,"Name":"Peer Group"},{"Id":143,"Name":"Quant Report"},{"Id":144,"Name":"ODD Report"},{"Id":145,"Name":"Activity Note"},{"Id":146,"Name":"Certificates of Formation"},{"Id":147,"Name":"Financial Statements Audit"},{"Id":148,"Name":"Articles of Association"},{"Id":149,"Name":"Limited Partnership Agreement"},{"Id":150,"Name":"Subscription Documents"},{"Id":151,"Name":"Advisory Agreement"},{"Id":153,"Name":"1.1+Call%2fMeeting+Notes"},{"Id":100,"Name":"White Papers"},{"Id":101,"Name":"Summary of Terms"},{"Id":103,"Name":"Conference Presentation"},{"Id":154,"Name":"2.1+Monthly+Reports"},{"Id":155,"Name":"2.2%2bQtrly%252fSemi-Ann%252fAnnual%2bRpts"},{"Id":156,"Name":"2.3+Performance+%2f+Estimates"},{"Id":157,"Name":"3.1%2bPitchbook%252fPresentation%252fDDQ"},{"Id":158,"Name":"3rd Party Research - Mgr/Fund"},{"Id":159,"Name":"3rd Party Research - Position"},{"Id":160,"Name":"Account Statements"},{"Id":161,"Name":"Agreed-Upon Procedure (AUP) Reports"},{"Id":162,"Name":"Business Continuity Plans (BCP)"},{"Id":163,"Name":"Call/Meeting Notes"},{"Id":164,"Name":"Capital Call Letters"},{"Id":165,"Name":"Code of Ethics"},{"Id":166,"Name":"Compliance Manual"},{"Id":167,"Name":"Confidentiality Agreements"},{"Id":168,"Name":"Counterparty Exposure Report"},{"Id":169,"Name":"Distribution / Redemption Notices"},{"Id":170,"Name":"E-Mail Exchange (mgr items that don't belong to other sub-cats)"},{"Id":171,"Name":"EnTrust Allocation Memo"},{"Id":172,"Name":"EnTrust DDQ"},{"Id":173,"Name":"EnTrust Exposure Template"},{"Id":174,"Name":"EnTrust Exposure Templates"},{"Id":175,"Name":"EnTrust Expsoure Template"},{"Id":176,"Name":"EnTrust Investment Memos"},{"Id":177,"Name":"EnTrust ODD Checklist"},{"Id":178,"Name":"EnTrust ODD Meeting Notes"},{"Id":179,"Name":"EnTrust Operational Dashboard"},{"Id":180,"Name":"Exposure / Attribution"},{"Id":181,"Name":"FAS 157 Reporting"},{"Id":182,"Name":"Firm AUM History"},{"Id":183,"Name":"Firm SAS 70 (Type I or II) Reports"},{"Id":184,"Name":"Firm/Fund AUM History"},{"Id":185,"Name":"Flash Notes"},{"Id":186,"Name":"Form ADV Part I"},{"Id":187,"Name":"Form ADV Part II"},{"Id":188,"Name":"Fund DDQ"},{"Id":189,"Name":"Fund Personnel Biographies"},{"Id":190,"Name":"Fund Personnel Changes"},{"Id":191,"Name":"Fund Pitch Book / Marketing Deck"},{"Id":192,"Name":"Fund Pitch Book / Marketing Decks"},{"Id":193,"Name":"Fund Prospectus"},{"Id":194,"Name":"Fund Structure Chart"},{"Id":195,"Name":"Historical Exposure / Historical Attribution"},{"Id":196,"Name":"Investment Manager Agreement (IMA)"},{"Id":197,"Name":"Investor Type Breakout"},{"Id":198,"Name":"Key Personnel Background Checks"},{"Id":199,"Name":"LPA / LLC Agreement"},{"Id":200,"Name":"Limited Partnership Agreement (LPA)"},{"Id":201,"Name":"Liquidity Breakout"},{"Id":202,"Name":"Mail Correspondence"},{"Id":203,"Name":"Manager DDQ"},{"Id":204,"Name":"Manager Reporting"},{"Id":205,"Name":"Monthly Flash Call"},{"Id":206,"Name":"Monthly Reports"},{"Id":207,"Name":"Monthly Reports (Investor Letter, Exposure, Allocation)"},{"Id":208,"Name":"Most Favored Nations (MFN) / Side Letters"},{"Id":209,"Name":"OPERA"},{"Id":210,"Name":"Opportunistic Investments"},{"Id":211,"Name":"Organizational Chart"},{"Id":212,"Name":"Other Firm Policy"},{"Id":213,"Name":"Other Firm Reporting"},{"Id":214,"Name":"Other Operational Reporting"},{"Id":215,"Name":"Performance"},{"Id":216,"Name":"Performance / Estimates"},{"Id":217,"Name":"Personal Trading Policy"},{"Id":218,"Name":"Pitchbook, Presentation, Manager/Fund DDQ"},{"Id":219,"Name":"Private Placement Memorandum (PPM)"},{"Id":220,"Name":"Proxy Voting Policy"},{"Id":221,"Name":"Quarterly, Semi-Annual, Annual Reports"},{"Id":222,"Name":"Redemption Documents"},{"Id":223,"Name":"Research Clippings : Manager Level"},{"Id":224,"Name":"Research Clippings : Position Level"},{"Id":225,"Name":"Service Provider Agreements / Descriptions of Service"},{"Id":226,"Name":"Service Provider Confirmations / DDQs"},{"Id":227,"Name":"Service Provider SAS 70 (Type I or II) Reports"},{"Id":228,"Name":"Temp"},{"Id":229,"Name":"Trade Error Policy"},{"Id":230,"Name":"Trade Flow / Operational Processes"},{"Id":231,"Name":"Valuation / Pricing Review Support"},{"Id":232,"Name":"Valuation / Pricing Source Breakout"},{"Id":233,"Name":"Valuation Policy"},{"Id":234,"Name":"zz_(DD-ODD)"},{"Id":235,"Name":"zz_(Fund Info)"},{"Id":236,"Name":"zz_(Governing Docs)"},{"Id":237,"Name":"zz_(Other)"},{"Id":238,"Name":"Daily/Weekly/Monthly Letters/Reports"},{"Id":239,"Name":"Quarterly Letters/Reports"},{"Id":240,"Name":"Annual Letters/Reports"},{"Id":242,"Name":"Meeting Notes"},{"Id":243,"Name":"Weekly Performance"},{"Id":244,"Name":"Mid-Month Performance"},{"Id":245,"Name":"Monthly Performance"},{"Id":246,"Name":"Quarterly Flash Bullets"},{"Id":247,"Name":"Activity Attachment"},{"Id":249,"Name":"Trade Slide"}]
HTML
<div class="card" *ngIf="DocumentUploadDetails && DocumentUploadDetails.DocumentEntities" style="margin-top: 10px" >
<div class="card-body" style="width:100%; text-align: left;">
<div style="overflow-x: hidden; overflow-y: hidden; ">
<div class="form-group row">
<div class="panel panel-default col-md-12 ">
<div class="panel-body">
<div id="grid-wrapper" [style.height.px]="GridHeight()" [style.width.%]="100"
style="float: left;">
<ag-grid-angular #agGrid class="ag-theme-balham" [gridOptions]="GridOptions"
style="width: 100%; height: 100%" [columnDefs]="ColumnDefs" rowHeight="30"
[rowData]="DocumentUploadDetails.DocumentEntities"
[editType]="editType"
(cellClicked)="onCellClicked($event)"
headerHeight="30" rowSelection="single">
</ag-grid-angular>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
组件
import { Component, Injectable, NgZone, ViewEncapsulation, ViewChild, Input } from '@angular/core'
import { OnInit } from '@angular/core'
import { Comparator } from '../utilities/comparator';
import { GridOptions, GridApi } from 'ag-grid-community';
import { DocumentUploadService } from '../services/documentUpload.service';
import { NotifyService } from '../utilities/notify.service';
import { number } from '@amcharts/amcharts4/core';
@Component({
selector: 'mgr-document-upload',
templateUrl: './documentUpload.component.html'
})
export class DocumentUploadComponent implements OnInit {
Files: Array<File>;
ColumnDefs: Array<any> = new Array<any>();
private Comparator: Comparator;
private Error: string;
private gridApi: GridApi;
public GridOptions: GridOptions;
private editClicked;
private editingRowIndex;
private editType;
ngZone: any;
windowHeight: any;
offset: number;
Loading: boolean;
public DocumentUploadDetails: any;
public params: any;
@Input() ManagerStrategyId = 5508;
MgrStrategyId = 5508;
ngOnInit() {
this.setGridOptions();
this.getDocumentUploadDetails();
}
constructor(private comparator: Comparator, private documentUploadService : DocumentUploadService, private notify: NotifyService,) {
this.Comparator = comparator;
this.editClicked = true;
this.getDocumentUploadDetails();
window.onresize = (e) => {
this.ngZone.run(() => {
this.windowHeight = window.innerHeight - this.offset;
setTimeout(() => {
if (!this.GridOptions || !this.GridOptions.api) {
return;
}
}, 500, true);
});
};
}
private getColumns(): Array<any> {
const self = this;
const columnDefs = new Array<any>();
columnDefs.push({ headerName: 'ID', field: 'DocumentId', hide: true ,editable: false});
columnDefs.push({ headerName: 'Document Type ID', field: 'DocumentTypeId', hide: true , editable: false});
columnDefs.push({ headerName: 'Type', field: 'DocumentTypeName', hide: false , editable: true , cellEditor: 'agSelectCellEditor',
cellEditorParams: {
values: this.DocumentUploadDetails.DocumentTypes,
cellRenderer: (params) => params.value.Name
}
});
columnDefs.push({ headerName: 'Document', field: 'DocumentName', hide: false, editable: true });
columnDefs.push({ headerName: 'Document Date', field: 'DocumentDate', hide: false , editable: true});
columnDefs.push(
{
cellRenderer: function (p) {
if (p.node.data && p.node.data.DocumentId) {
var eSpan = self.getDeleteSpan();
eSpan.addEventListener('click', function () {
var self2 = self;
//self2.onEdit();
});
return eSpan;
}
else {
return '';
}
}, comparator: this.comparator.StringComparator, width: 50, cellStyle: { textAlign: 'center' }, cellClass: 'align-center', headerName: "Edit", pinned: 'right'
});
columnDefs.push(
{
cellRenderer: function (p) {
if (p.node.data && p.node.data.DocumentId) {
var eSpan = self.getDeleteSpan();
eSpan.addEventListener('click', function () {
var self2 = self;
self2.Delete(p.node.data.DocumentId);
});
return eSpan;
}
else {
return '';
}
}, comparator: this.comparator.StringComparator, width: 50, cellStyle: { textAlign: 'center' }, cellClass: 'align-center', headerName: "Delete", pinned: 'right'
});
this.editType = 'fullRow';
return columnDefs;
}
onEdit() {
// this.params = this.GridOptions.api.getEditingCells;
// this.editClicked = !this.editClicked;
// this.params.api.setFocusedCell(this.params.node.rowIndex, 'action');
// this.params.api.startEditingCell({
// rowIndex: this.params.node.rowIndex,
// colKey: 'action'
// });
}
private getDeleteSpan() {
var eSpan = document.createElement('a');
eSpan.innerHTML = '<div style="cursor:pointer;max-width: 50px"><i class="far fa-trash-alt fontColor" aria-hidden="true"></i></div>';
return eSpan;
}
GridHeight() {
if (!this.windowHeight) {
this.windowHeight = window.innerHeight - this.offset + 10;
}
return this.windowHeight;
}
private initGrid() {
const self = this;
}
setGridOptions() {
this.GridOptions = {
columnDefs: this.getColumns(),
enableFilter: true,
enableColResize: true,
animateRows: true,
enableSorting: true,
onGridReady: e => {
if (!e || !e.api) {
return;
}
this.gridApi = e.api;
this.setDefaultSortOrder();
},
onGridSizeChanged: () => this.GridOptions.api.sizeColumnsToFit(),
};
}
onCellClicked($event){
// check whether the current row is already opened in edit or not
if(this.editingRowIndex != $event.rowIndex) {
console.log($event);
$event.api.startEditingCell({
rowIndex: $event.rowIndex,
colKey: $event.column.colId
});
this.editingRowIndex = $event.rowIndex;
}
}
setDefaultSortOrder() {
const defaultSortModel = [
{ colId: 'DocumentDate', sort: 'desc' }
];
this.GridOptions.api.setSortModel(defaultSortModel);
}
onGridSizeChanged(params) {
const gridWidth = document.getElementById('grid-wrapper').offsetWidth;
const columnsToShow = [];
const columnsToHide = [];
let totalColsWidth = 0;
const allColumns = params.columnApi.getAllColumns();
for (let i = 0; i < allColumns.length; i++) {
const column = allColumns[i];
totalColsWidth += column.getMinWidth();
if (totalColsWidth > gridWidth) {
columnsToHide.push(column.colId);
} else {
columnsToShow.push(column.colId);
}
}
params.columnApi.setColumnsVisible(columnsToShow, true);
params.columnApi.setColumnsVisible(columnsToHide, false);
params.api.sizeColumnsToFit();
}
private Delete(Id: number) {
if (Id !== 0) {
this.Error = '';
this.documentUploadService
.deleteDocument(Id)
.then((result) => {
if (result) {
this.notify.success('Document Successfully Deleted');
// this.ClassficationOverrideDetailsEvent.next('init');
}
}).catch(err => {
this.notify.error('An Error Has Occured While Deleting Document');
});
}
}
public getDocumentUploadDetails() {
if (this.MgrStrategyId != null) {
this.Loading = true;
this.initGrid();
// this.spinner.show();
this.documentUploadService.getDocumentUploadDetails(this.MgrStrategyId)
.subscribe(data => {
this.DocumentUploadDetails = data;
this.ColumnDefs = this.getColumns();
this.Loading = false;
setTimeout(() => {
this.GridOptions.api.sizeColumnsToFit();
this.Loading = false;
}, 100, true);
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
});
}
}
}
根据建议的解决方案更新了代码
为了使用agSelectCellEditor,我通过了以下选项
this.DocumentTypesForDropDown = this.DocumentUploadDetails.DocumentTypes.map(x => x.Name);
我还按照建议删除了对this.getColumns()的调用,并将其移至init方法
我的Init方法现在看起来像这样
ngOnInit() {
this.getDocumentUploadDetails();
this.setGridOptions();
this.setColumns();
}
当我从服务中获取DocumentType时,可以通过在getDocumentUploadDetails方法中设置this.DocumentTypesForDropDown值来进行小的更改。
public getDocumentUploadDetails() {
if (this.MgrStrategyId != null) {
this.Loading = true;
this.initGrid();
// this.spinner.show();
this.documentUploadService.getDocumentUploadDetails(this.MgrStrategyId)
.subscribe(data => {
this.DocumentUploadDetails = data;
this.DocumentTypesForDropDown = this.DocumentUploadDetails.DocumentTypes.map(x => x.Name);
// this.ColumnDefs = this.getColumns();
this.Loading = false;
setTimeout(() => {
this.GridOptions.api.sizeColumnsToFit();
this.Loading = false;
}, 100, true);
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
});
}
}
}
完成上述操作后,我没有出现任何错误,并且显示了空白网格
更新2
_documentTypes: any;
get DocumentTypes(): any {
return this._documentTypes;
}
@Input('DocumentTypes')
set DocumentTypes(value: any) {
this._documentTypes = value;
if(this._documentTypes.length > 0) {
this.DocumentTypesForDropDown = this._documentTypes.map(x => x.text);
this.getDocumentUploadDetails();
this.setGridOptions();
this.setColumns();
}
}
答案 0 :(得分:0)
您的代码有很多问题,我将尽力解决每个问题。
与下拉列表有关的主要问题,您的下拉列表具有以下代码:
columnDefs.push({
headerName: 'Type', field: 'DocumentTypeName', hide: false, editable: true, cellEditor: 'agSelectCellEditor',
cellEditorParams: {
values: this.DocumentUploadDetails.DocumentTypes,
cellRenderer: (params) => params.value.Name
}
使用agSelectCellEditor时,可以传递给cellEditorParams
的唯一参数是values
(请参阅文档)。
因此,如果您想使用对象作为下拉菜单,则需要使用agRichSelectCellEditor来处理对象。 agrichselectcelleditor
将具有cellRenderer
参数,尽管这是ag-grid的企业功能。
因此,如果您希望在下拉列表中按名称列出选项,建议您创建一系列下拉列表问题,并在其中仅包含文档类型名称。
您可以执行以下操作:
this.DocumentTypesForDropDown = this.DocumentUploadDetails.DocumentTypes.map(x => x.Name);
这将包含所有文档类型名称的数组。然后,您可以将其作为下拉列表的参数提供给列定义,因此列定义应如下所示:
this.ColumnDefs.push({
headerName: 'Type', field: 'DocumentTypeName', hide: false, editable: true, cellEditor: 'agSelectCellEditor',
cellEditorParams: {
values: this.DocumentTypesForDropDown
}
});
您可能遇到的另一个问题是下拉列表不会显示任何内容;这是因为在创建列定义之前,必须定义下拉菜单的值; cellEditorParams
不采用动态参数。
在代码中继续在两个位置设置列定义:setGridOptions()
方法和getDocumentUploadDetails()
方法。
我建议在setGridOptions()
和getDocumentUploadDetails()
方法中删除列定义的设置,而在ngOnInit()
中进行设置。
我还为您的代码创建了简化的StackBlitz,这应该有助于更好地理解我的答案。