UNPKG

ag-grid-enterprise

Version:

ag-Grid Enterprise Features

178 lines (149 loc) 6.16 kB
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>`; @RefSelector('eDetailGrid') private eDetailGrid: HTMLElement; @Autowired('gridOptionsWrapper') private gridOptionsWrapper: GridOptionsWrapper; @Autowired('environment') 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; }