我试图使用角网格(AG-网格)树来显示一个树像在文档中提供的示例:创建角网格(AG-网格)与异步数据加载
http://www.angulargrid.com/example-file-browser/index.php
在给出的例子中,所有的数据都已经提供。行组展开时如何使用异步数据加载?我的猜测是我需要编写自己的组行渲染器。
我试图使用角网格(AG-网格)树来显示一个树像在文档中提供的示例:创建角网格(AG-网格)与异步数据加载
http://www.angulargrid.com/example-file-browser/index.php
在给出的例子中,所有的数据都已经提供。行组展开时如何使用异步数据加载?我的猜测是我需要编写自己的组行渲染器。
网格不支持延迟加载树数据。所以是的,你必须编写自己的cellRenderer来实现这一点。
PS我是ag-Grid的作者,所以你可以把这个答案当作福音!
只是一个想法,但我认为你可以在第一个单元格添加一个占位符子行到组“载入中...”,同组的onRowGroupOpened事件设置,使Ajax调用从服务器获取数据,onreadystatechange然后添加新行并替换占位符。初始占位符行可以包含服务器计算的总值,以驱动组行的单元格中的聚合(总计)值,当实际数据替换占位符时这些值将保持不变。
我想出了一个基本的测试方法。这并不完美,因为网格在每次扩展之后都会重建(我找不到一个优雅的方式来添加新行),但它确实有效。
脚本的最顶部是AJAX调用细节。虽然这发生在后面的流程中,但我把它放在顶部,这样如果服务器收到这个请求,它会提供数据并退出,而不会再次加载页面。或者,你可以把它放到另一个文件中。
<?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;
}
?>
然后紧接着而来的,是正常的HTML页面多一点点的PHP的头在JavaScript中:
<!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 - 如何更优雅添加新行任何想法并保留团队扩张的状态?
我最近在我的React.js应用程序中遇到了同样的问题,并找到了解决方案。这与@leden发布的内容类似,但我发现解决方案如何维护表行之间的当前行扩展更新。
解决的方法如下:
添加虚拟子行的每个顶级一行。可以为空或者可以在第一列中加载...字符串。
在事件getNodeChildDetails(每当您更新表rowData时调用)时,您可以指定是否应该展开行。所以我们的想法是,我们跟踪什么是扩大和什么不是。
getNodeChildDetails = (rowItem) => {
if (rowItem.children) {
return {
group: true,
expanded: rowItem.id in this.expandedRows,
children: rowItem.children,
};
}
else {
return null;
}
};
On事件rowGroupOpened我们跟踪哪些行被展开。
rowGroupOpened = (param) => {
const id= param.node.data.id;
if(!param.node.expanded) {
delete this.expandedRows[id];
return;
}
this.expandedRows[id] = true;
if (param.node.data.children.length !== 1) { // Here we need to check if only dummy row is present
return;
}
this.api.showLoadingOverlay();
// Here I simulate fetching data from server
setTimeout(() => {
this.rowData.forEach((e) => {
if (e.id == id) {
e.children = [
// Add fetch rows
]
}
});
this.api.setRowData(this.rowData); // Setting data, will trigger getNodeChildDetails call on each row
this.api.hideOverlay();
}, 1000);
};
嘿尼尔,如果我不要求太多,能否请您详细一点?由于编写你自己的groupRowRenderer会扔掉很多标准和有用的行为(扩展,折叠和所有这些),我在考虑是否有一种侵入性较小的方法。 例如,是否可以将ajax调用onRowExpand?或者节点将没有子节点(在点击/尝试扩展时)将不允许调用“onRowExpand”? – Zubzob
另外,这不会影响虚拟化功能吗? – Zubzob
没有看到它会如何影响行虚拟化。如果该组未扩展,则不会考虑这些行进行渲染,因此没有理由将它们包含在虚拟化中。 –