问题描述
我有一个相当标准的带有嵌套组件的ag-grid设置,如下所示:
import { Component } from '@angular/core';
import * as agGrid from 'ag-grid-community';
import { nestedMatExpansionPanelComponent } from './nested-mat-expansion-panel/nested-mat-expansion-panel.component';
@Component({
selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'aggrid-material-expansion-panel';
dataToShow = [
{ name: 'name1',companyCountry: 'UK',reference: 'Ref 1' },{ name: 'name2',companyCountry: 'Germany',reference: 'Ref 2' },{ name: 'name3',companyCountry: 'France',reference: 'Ref 3' },{ name: 'name4',reference: 'Ref 4' },{ name: 'name5',companyCountry: 'USA',reference: 'Ref 5' },];
columnDefs = [
// tslint:disable-next-line: max-line-length
{ headerName: 'Name',colId: 'name',cellRenderer: 'nestedMatExpansionPanelRenderer',filter: false,sortable: false },{ headerName: 'Country',field: 'companyCountry',sortable: true,filter: true },{ headerName: 'Reference',field: 'reference',filter: true }
];
// agG_rid
gridApi: agGrid.GridApi;
gridColumnApi: agGrid.ColumnApi;
gridOptions: agGrid.GridOptions = {};
public defaultColDef: any;
public columnTypes: any;
public context: any;
public frameworkComponents: any;
public sortingOrder: any;
constructor() {
this.initTable();
}
public onGridReady(params: any) {
// this.gridApi = this.gridOptions.api;
// this.gridColumnApi = this.gridOptions.columnApi;
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
public initTable(): void {
this.defaultColDef = {
flex: 1,autoHeight: true,editable: false,enablebrowserTooltips: true,resizable: true,filter: 'agTextColumnFilter',suppressMenu: true,floatingFilterComponentParams: { suppressFilterButton: true },filterParams: { newRowsAction: 'keep' },};
this.columnTypes = {
numericColumn: { filter: 'agnumericColumnFilter' },dateColumn: {
filter: 'agDateColumnFilter',filterParams: {
newRowsAction: 'keep',comparator(filterLocalDateAtMidnight,cellValue) {
const dateParts = cellValue.split('/');
const day = Number(dateParts[2]);
const month = Number(dateParts[1]) - 1;
const year = Number(dateParts[0]);
const cellDate = new Date(day,month,year);
if (cellDate < filterLocalDateAtMidnight) {
return -1;
} else if (cellDate > filterLocalDateAtMidnight) {
return 1;
} else {
return 0;
}
}
}
}
};
this.sortingOrder = ['desc','asc'];
this.context = { componentParent: this };
this.frameworkComponents = {
nestedMatExpansionPanelRenderer: nestedMatExpansionPanelComponent,};
}
public onRowClicked($event) {
//
}
}
您可以看到我有
autoHeight: true,
因此,每行应根据嵌入的手风琴的扩展状态自动获得正确的高度,但该行的输出高度计算错误:
如何根据嵌入式扩展面板的状态自动调整每行的高度,以便在打开或关闭每行内部的扩展面板时不会有多余的空白空间?
解决方法
基本上,您遇到的问题是MatExpansionPanel
和如何在ag-grid中计算autoHeight
的综合问题。
使用autoHeight,他们从单元格中取出内容,并将其放在临时的不可见元素中,可能位于document.body
元素中。问题在于,此时此元素尚未应用适当的样式,它显示了您面对的高度。因此,autoHeight
不是这里的解决方案,应将其设置为false
。
那么如何实现手动高度计算。 Ag-grid在setRowHeight
上具有node
属性。您可以用来设置高度。从那里需要通知网格API,所有行的高度都已更改,可以通过调用onRowHeightChanged()
在此基础上重新计算。获得这种通信的一种方法是使用普通服务:
@Injectable()
export class GridService {
readonly updateHeight$ = new Subject<void>();
}
在您在模板中创建ag-grid的组件中,应将此服务器添加到providers数组并收听主题(带有反跳以确保最初计算所有行):
@Component({
// ...,providers: [GridService]
})
export class GridComponent {
gridApi: agGrid.GridApi;
constructor(private gs: GridService) {
this.gs.updateHeight$.pipe(
debounceTime(1)
).subscribe(() => {
this.gridApi?.onRowHeightChanged();
});
}
onGridReady(params: any) {
this.gridApi = params.api;
}
}
现在,在单元格渲染器框架组件中需要以下逻辑:
export class ExpansionPanelComponent implements ICellRendererAngularComp,AfterViewInit {
public params: ICellRendererParams;
constructor(private el: ElementRef<HTMLElement>,private gs: GridService) {}
agInit(params: ICellRendererParams): void {
this.params = params;
}
ngAfterViewInit(): void {
// inside setTimeout because the accordion is not properly sized (bug) and it will be too big
setTimeout(() => this.updateHeight());
}
updateHeight(): void {
// inside setTimeout because the accordion is not properly sized (bug) and it will be too big
setTimeout(() => {
this.params?.node.setRowHeight(this.el.nativeElement.offsetHeight);
this.gs.updateHeight$.next();
});
}
refresh(params: any): boolean {
return false;
}
}
我创建了一个有效的提取请求here
要删除左侧的填充,可以将以下内容添加到columnDefs数组中:
columnDefs = [
{
//...,cellRenderer: 'nestedMatExpansionPanelRenderer',cellStyle: { 'padding-left': 0 }
},// ...
]