6

我正在尝试使用 angular-grid (ag-grid) 来显示类似于文档中提供的示例中的树:

http://www.angulargrid.com/example-file-browser/index.php

在给定的示例中,已经提供了所有数据。展开行组时如何使用异步数据加载?我的猜测是我需要编写自己的组行渲染器。

4

3 回答 3

4

我最近在我的 React.js 应用程序中遇到了同样的问题并找到了解决方案。它类似于@leden 发布的内容,但我找到了如何在表行更新之间维护当前行扩展的解决方案。

解决方法如下:

  1. 为每个顶级行添加虚拟子行。可以为空,也可以加载...字符串,例如在第一列中。

  2. 在每次更新表 rowData 时调用的事件 getNodeChildDetails 上,您可以指定是否应扩展行。所以我们的想法是我们跟踪什么是扩展的,什么不是。

    getNodeChildDetails = (rowItem) => {
      if (rowItem.children) {
        return {
          group: true,
          expanded: rowItem.id in this.expandedRows,
          children: rowItem.children,
        };
      }
      else {
        return null;
      }
    };
    
  3. 在事件 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);
      };
    
于 2017-02-16T12:02:04.890 回答
3

网格不支持开箱即用的延迟加载树数据。所以是的,你必须编写自己的 cellRenderer 来实现这一点。

PS我是ag-Grid的作者,所以你可以把这个答案当作福音!

于 2015-09-02T20:35:31.867 回答
0

只是一个想法,但我认为您可以在第一个单元格中使用“正在加载... ”将单个占位符子行添加到组中,并将组的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 页面,头部的 javascript 中包含更多的 php:

<!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 - 关于如何更优雅地添加新行并保持组扩展状态的任何想法?

于 2016-05-29T19:35:01.920 回答