For Ag grid Master/Detail, is there a way to add more than one detail? In the eg. it only eg with one detail only.
For Ag grid Master/Detail, is there a way to add more than one detail? In the eg. it only eg with one detail only.
It sounds like you are asking how to have a single master with multiple detail grids.
You will need to create your own detailCellRender class/object. In the template definition for your class, you create as many detail grids as you need. In the init method, you initialize the grid(s) and set their data.
It is very important to remember the life-cycle of a cell renderer! The grid only exists while it is visible.
class MultipleDetailCellRenderer {
constructor() {
this.eGui = document.createElement("div");
}
init(params) {
this.rowId = params.node.id;
this.masterGridApi = params.api;
// Note: assume data has an id field,
// whatever you have defined in your column def should be available
this.id=params.data.id;
/* Build the div for the grid 1 */
var grid_01 = document.createElement("div");
grid_01.id = `grid01_${this.id}`;
grid_01.classList = "ag-details-row-grid01";
this.eGui.appendChild(grid_01);
this.grid_01 = grid_01;
/* Build the div for grid 2 */
var grid_02 = document.createElement("div");
grid_02.id = `grid02_${this.id}`;
grid_02.classList = "ag-details-row-grid02";
this.eGui.appendChild(grid_02);
this.grid_02 = grid_02;
// Theoretically, you can have more detail grids here too,
// just go through the exercise of wiring them in
if (this.grid_01 !== undefined && this.grid_02 !== undefined) {
this.createDetailsGrids(params);
this.registerDetailsWithMaster(params.node);
this.loadRowData(params);
window.setTimeout(() => {
if (this.grid_01Options.api) {
this.grid_01Options.api.doLayout();
}
if (this.grid_02Options.api) {
this.grid_02Options.api.doLayout();
}
}, 0);
}
}
getGui() {
return this.eGui;
}
refresh(params) {
return false;
}
destroy(params) {}
buildGridOptions() {
var grid_01Options = {};
grid_01Options.columnDefs = {}; // your column defs, required
grid_01Options.getContextMenuItems = {}; // your context menu items, not required
grid_01Options.popupParent = document.querySelector("#DivWhereMasterGridLives");
// any event handlers for the detail grids go here
grid_01Options.onCellDoubleClicked = params => {console.log("onCellDoubleClicked", params);};
grid_01Options.onCellValueChanged = params => {console.log("onCellValueChanged", params);};
// grid_01Options.rowClassRules = classRules; // css conditional row styling
/* Config the 2nd detail grid */
var grid_02Options = {};
grid_02Options.columnDefs = {}; // your column defs, required
grid_02Options.getContextMenuItems = {}; // your context menu items, not required
grid_02Options.popupParent = document.querySelector("#DivWhereMasterGridLives");
// any event handlers for the detail grids go here
grid_02Options.onCellDoubleClicked = params => {console.log("onCellDoubleClicked", params);};
grid_02Options.onCellValueChanged = params => {console.log("onCellValueChanged", params);};
// grid_02Options.rowClassRules = classRules; // css conditional row styling
this.grid_01Options = grid_01Options;
this.grid_02Options = grid_02Options;
}
setRowData(grid01_data, grid02_data) {
if (this.grid_01Options.api) {
this.grid_01Options.api.setRowData(grid01_data);
}
if (this.grid_02Options.api) {
this.grid_02Options.api.setRowData(grid02_data);
}
}
loadRowData(params) {
var grid01_data = []; // work your magic to get the data for grid 1
var grid02_data = []; // work your magic to get the data for grid 2
this.setRowData(grid01_data,grid02_data);
}
registerDetailsWithMaster(node) {
var grid_01Info = {
id: this.rowId,
api: this.grid_01Options.api,
columnApi: this.grid_01Options.columnApi
};
var grid_02Info = {
id: this.rowId,
api: this.grid_02Options.api,
columnApi: this.grid_02Options.columnApi
};
this.masterGridApi.addDetailGridInfo(`grid01_${this.id}`, grid_01Info);
this.masterGridApi.addDetailGridInfo(`grid02_${this.id}`, grid_02Info);
this.addDestroyFunc = () => {
this.masterGridApi.removeDetailGridInfo(`grid01_${this.id}`);
this.masterGridApi.removeDetailGridInfo(`grid02_${this.id}`);
node.addDetailGridInfo = null;
};
}
createDetailsGrids(params) {
this.buildGridOptions();
new agGrid.Grid(this.grid_01, this.grid_01Options, {
$scope: params.$scope,
$compile: params.$compile
});
new agGrid.Grid(this.grid_02, this.grid_02Options, {
$scope: params.$scope,
$compile: params.$compile
});
this.grid_01Options.api.setDomLayout("autoHeight");
this.grid_02Options.api.setDomLayout("autoHeight");
this.addDestroyFunc = () => {
if(this.grid_01Options.api) {
this.grid_01Options.api.destroy();
}
if(this.grid_02Options.api) {
this.grid_02Options.api.destroy();
}
};
}
}
Then in your master grid definition
$scope.masterGridOpts.masterDetail = true;
$scope.masterGridOpts.detailCellRenderer = MultipleDetailCellRenderer;
$scope.masterGridOpts.detailCellRendererParams = {};
According to agGrid's own website, this is now supported:
https://blog.ag-grid.com/introducing-version-20-of-ag-grid/
I've learned not to trust agGrid's documentation, until I see a working example.
Has anyone seen an example of this yet, or managed to get this working ?