ag-grid-enterprise
Version:
ag-Grid Enterprise Features
178 lines (149 loc) • 6.16 kB
text/typescript
import {
_,
Grid,
GridApi,
RowNode,
Component,
Autowired,
RefSelector,
GridOptions,
DetailGridInfo,
GridOptionsWrapper,
ICellRendererParams,
Environment
} from "ag-grid-community";
export class DetailCellRenderer extends Component {
private static TEMPLATE =
`<div class="ag-details-row">
<div ref="eDetailGrid" class="ag-details-grid"/>
</div>`;
private eDetailGrid: HTMLElement;
private gridOptionsWrapper: GridOptionsWrapper;
private environment: Environment;
private detailGridOptions: GridOptions;
private masterGridApi: GridApi;
private rowId: string;
public init(params: IDetailCellRendererParams): void {
this.rowId = params.node.id;
this.masterGridApi = params.api;
this.selectAndSetTemplate(params);
if (_.exists(this.eDetailGrid)) {
this.addThemeToDetailGrid();
this.createDetailsGrid(params);
this.registerDetailWithMaster(params.node);
this.loadRowData(params);
setTimeout(() => {
// ensure detail grid api still exists (grid may be destroyed when async call tries to set data)
if (this.detailGridOptions.api) {
this.detailGridOptions.api.doLayout();
}
},0);
} else {
console.warn('ag-Grid: reference to eDetailGrid was missing from the details template. ' +
'Please add ref="eDetailGrid" to the template.');
}
}
private addThemeToDetailGrid(): void {
// this is needed by environment service of the child grid, the class needs to be on
// the grid div itself - the browser's CSS on the other hand just inherits from the parent grid theme.
let theme = this.environment.getTheme();
if (_.exists(theme)) {
_.addCssClass(this.eDetailGrid, theme);
}
}
private registerDetailWithMaster(rowNode: RowNode): void {
let gridInfo: DetailGridInfo = {
id: this.rowId,
api: this.detailGridOptions.api,
columnApi: this.detailGridOptions.columnApi
};
// register with api
this.masterGridApi.addDetailGridInfo(this.rowId, gridInfo);
// register with node
rowNode.detailGridInfo = gridInfo;
this.addDestroyFunc( ()=> {
this.masterGridApi.removeDetailGridInfo(this.rowId); // unregister from api
rowNode.detailGridInfo = null; // unregister from node
});
}
private selectAndSetTemplate(params: ICellRendererParams): void {
let paramsAny = <any> params;
if (_.missing(paramsAny.template)) {
// use default template
this.setTemplate(DetailCellRenderer.TEMPLATE);
} else {
// use user provided template
if (typeof paramsAny.template === 'string') {
this.setTemplate(<string>paramsAny.template);
} else if (typeof paramsAny.template === 'function') {
let templateFunc: TemplateFunc = <TemplateFunc> paramsAny.template;
let template = templateFunc(params);
this.setTemplate(template);
} else {
console.warn('ag-Grid: detailCellRendererParams.template should be function or string');
this.setTemplate(DetailCellRenderer.TEMPLATE);
}
}
}
private createDetailsGrid(params: IDetailCellRendererParams): void {
// we clone the detail grid options, as otherwise it would be shared
// across many instances, and that would be a problem because we set
// api and columnApi into gridOptions
let gridOptions = params.detailGridOptions;
if (_.missing(gridOptions)) {
console.warn('ag-Grid: could not find detail grid options for master detail, ' +
'please set gridOptions.detailCellRendererParams.detailGridOptions');
}
// IMPORTANT - gridOptions must be cloned
this.detailGridOptions = _.cloneObject(gridOptions);
new Grid(this.eDetailGrid, this.detailGridOptions, {
seedBeanInstances: {
// a temporary fix for AG-1574
// AG-1715 raised to do a wider ranging refactor to improve this
agGridReact: params.agGridReact,
// AG-1716 - directly related to AG-1574 and AG-1715
frameworkComponentWrapper: params.frameworkComponentWrapper
}
});
this.addDestroyFunc( () => this.detailGridOptions.api.destroy() );
}
private loadRowData(params: IDetailCellRendererParams): void {
let userFunc = params.getDetailRowData;
if (!userFunc) {
console.warn('ag-Grid: could not find getDetailRowData for master / detail, ' +
'please set gridOptions.detailCellRendererParams.getDetailRowData');
return;
}
let funcParams: any = {
node: params.node,
data: params.data,
successCallback: this.setRowData.bind(this)
};
userFunc(funcParams);
}
private setRowData(rowData: any[]): void {
// ensure detail grid api still exists (grid may be destroyed when async call tries to set data)
if (this.detailGridOptions.api) {
this.detailGridOptions.api.setRowData(rowData);
}
}
}
export interface IDetailCellRendererParams extends ICellRendererParams {
detailGridOptions: GridOptions;
getDetailRowData: GetDetailRowData;
agGridReact: any;
frameworkComponentWrapper: any;
}
export interface GetDetailRowData {
(params: GetDetailRowDataParams): void;
}
export interface GetDetailRowDataParams {
// details for the request,
node: RowNode;
data: any;
// success callback, pass the rows back the grid asked for
successCallback(rowData: any[]): void;
}
interface TemplateFunc {
(params: ICellRendererParams): string;
}