Just an idea, but I think that you could add a single placeholder child row to the group with "loading..." in the first cell, with the group's onRowGroupOpened event set to make the ajax call to get the data from the server, with the onreadystatechange then adding the new rows and replacing the placeholder one. The initial placeholder row can contain server-calculated total values to drive aggregation (total) values in the group row's cells, which would remain the same when real data replaces the placeholder.
I have come up with a basic test of the approach. It's not perfect, as the grid rebuilds after each expansion (I can't find an elegant way to just append the new rows), but it does work.
At the very top of the script is the AJAX call for detail. Although this happens later in the flow I put it at the top, so that if the server receives this request, it provides data and exits, without loading the page again. Alternatively you could just put it into another file.
<?php
if (isset($_REQUEST['g'])) { // this is the AJAX request for child data (called later, but needed at the start of the script)
// get connection to database
require_once 'db_connection.php'; $dbh=getConnection();
// query data to array
$sql="SELECT accounts.description AS account, '' AS info,
tx.amnt AS amount, 1 AS transactions
FROM tx
INNER JOIN accounts ON tx.account=accounts.account_id
WHERE accounts.description='".$_REQUEST['g']."'";
$data=array();
$result = $dbh->query($sql);
while ($row = $result->fetch_assoc()) {
$data[]=$row;
}
$result->free();
// return data as JSON
print json_encode($data, JSON_NUMERIC_CHECK);
exit;
}
?>
Then immediately after that comes a normal HTML page with a little bit more php within the javascript in the head:
<!DOCTYPE html>
<html>
<head>
<script src="lib/ag-grid-enterprise-master/dist/ag-grid-enterprise.js"></script>
<script>
// get JSON for initial group-level data from server with a little snippet of php which is called when the page is first loaded
var rowData =
<?php
// get connection to the database
require_once 'db_connection.php'; $dbh=getConnection();
// query data to array
$sql = "SELECT description AS account, 'loading...' AS info,
SUM(tx.amnt) AS amount, COUNT(tx.tx_id) AS transactions
FROM accounts
INNER JOIN tx ON accounts.account_id=tx.account
GROUP BY accounts.account_id";
$data=array();
$result = $dbh->query($sql);
while ($row = $result->fetch_assoc()) {
$data[]=$row;
}
$result->free();
// inject the JSON into the javascript assignment to rowData
print json_encode($data, JSON_NUMERIC_CHECK);
?>;
// (back in javascript again)
// event function for when a group is expanded
function getChildRows(data) {
if (data.node.allLeafChildren) {
if (data.node.allLeafChildren.length > 0) {
if (data.node.allLeafChildren[0].data.info==="loading...") {
// data for this group has not yet been loaded, so make AJAX request for it
var xmlHttp=new XMLHttpRequest();
xmlHttp.onreadystatechange=function() {
if ((xmlHttp.readyState===4) && (xmlHttp.status === 200)) {
// call function to add the new rows to the grid
addRecords(JSON.parse(xmlHttp.responseText));
}
};
var requestParameters="g="+encodeURIComponent(data.node.key);
xmlHttp.open("POST", "index.php", true); // call to this same script
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.send(requestParameters);
}
}
}
}
function addRecords(data) {
var x; var d=new Array();
var acc=data[0].account;
for(x in gridOptions.api.inMemoryRowModel.rootNode.allLeafChildren) {
if (gridOptions.api.inMemoryRowModel.rootNode.allLeafChildren[x].data.account===acc) {
// this is group we are replacing with new data
for (x in data) {
d.push(data[x]);
}
} else {
// this node is just the data as currently loaded to the grid (no change)
d.push(gridOptions.api.inMemoryRowModel.rootNode.allLeafChildren[x].data);
}
}
gridOptions.api.setRowData(d);
}
// set up the grid (standard stuff)
var columnDefs = [
{headerName: "Account", field: "account", rowGroupIndex: 0, cellRenderer: "group", cellRendererParams : {suppressCount: true} },
{headerName: "Info", field: "info"},
{headerName: "Amount", field: "amount", aggFunc:"sum"},
{headerName: "Transactions", field: "transactions", aggFunc:"sum"}
];
var gridOptions = {
columnDefs: columnDefs,
rowData: rowData,
groupSuppressAutoColumn: true,
onRowGroupOpened: getChildRows /* event created above */
}
document.addEventListener("DOMContentLoaded", function() {
var eGridDiv = document.querySelector('#myGrid');
new agGrid.Grid(eGridDiv, gridOptions);
});
</script>
</head>
<body>
<div id="myGrid" style="height: 100%;" class="ag-fresh"></div>
</body>
</html>
@Niall - any ideas on how to add the new rows more elegantly and retain status of group expansion?