【问题标题】:AG-Grid with TreeData using Enterprise Row ModelAG-Grid 与 TreeData 使用企业行模型
【发布时间】:2022-04-20 05:25:27
【问题描述】:

我正在尝试使用 ag-grid 实现带有树数据的网格。我正在使用企业行模型。问题是当对数据进行硬编码并通过 setRowData 进行设置时,网格会完美显示。但是,当通过企业行模型加载数据时,网格不会呈现为树。事实上,getDataPath 回调甚至没有被调用。

是否有人设法将树数据功能与企业数据源一起使用,因为这似乎没有记录在案?

谢谢

【问题讨论】:

  • 您找到解决方案了吗?

标签: ag-grid


【解决方案1】:

我假设企业行模型是指服务器端行模型,因此您期望来自服务器的树状结构数据。在这种情况下,我已经能够在 Ag-grid 中结合以下功能:无限滚动 + 树数据 + 服务器端行模型。 我什至实现了自定义过滤,它按预期工作。

数据流:

  1. 我们必须使用 ag-grid 的配置启用服务器端行模型。
  2. 在 JavaScript 中实现一个假服务器和代理数据源对象。数据源对象必须包含一个名为“getRows”的方法,ag-grid 可以调用该方法。每次用户执行诸如滚动、过滤、排序、展开父行以查看子行等操作时,Ag-grid 都会调用此方法。
  3. 实现一个名为 onGridReady() 的方法,ag-grid 每次尝试第一次渲染网格时都会调用该方法,然后将 server 和 dataSource 对象传递给 onGridReady() 中的 ag-grid 内部 API。李>

实现(结合使用 ReactJS 和纯 JavaScript):

  1. 在 ag-grid 中启用服务器端行模型。

    <AgGridReact
       columnDefs={this.columnDefs}
       rowModelType={this.rowModelType}
       treeData={true}
       isServerSideGroup={this.isServerSideGroup}
       getServerSideGroupKey={this.getServerSideGroupKey}
       onGridReady={this.onGridReady}
       cacheBlockSize={50}
     />
    
  2. 在 JavaScript 中实现一个假服务器和代理数据源对象。

    要使用服务器端行模型,您需要在 JavaScript 中的 ServerSideDataSource 实例中提供数据。 ServerSideDataSource 的实例必须有一个名为 getRows() 的方法,每次用户向下滚动以获取下一组数据或展开一行以在树结构中检索其子记录时,ag-grid 都会调用该方法。

    ServerSideDataSource 的构造函数接受代理数据容器,通常用于 ag-grid 示例:fakeServer 实例。 fakeServer 的单例实例保存从真实服务器接收到的数据,并保留它以供以下使用:

    a) 当 ag-grid 想要显示子记录时,它会调用 getRows。因为我们提供了这个 ServerSideDataSource 的自定义实现,所以我们可以在 getRows 中编写逻辑来从这个 fakeServer 实例中提取数据。

    b) 当 ag-grid 尝试在无限滚动或分页中显示下一组数据时,它会检查上次检索到多少数据以请求无限滚动中的下一个块(使用 startRow 和 endRow 变量)。

  3. 定义假服务器和服务器端数据源:

    function createFakeServer(fakeServerData) {
     function FakeServer(allData) {
       this.data = allData;
     }
    
     FakeServer.prototype.getData = function(request) {
       function extractRowsFromData(groupKeys, data) {
         if (groupKeys.length === 0) {
           return data; //child records are returned from here.
         }
         var key = groupKeys[0];
         for (var i = 0; i < data.length; i++) {
           if (data[i].employeeId === key) {
             return extractRowsFromData(groupKeys.slice(1), data[i].children.slice());
           }
         }
       }
       return extractRowsFromData(request.groupKeys, this.data);
     };
     return new FakeServer(fakeServerData);
    }
    
    function createServerSideDatasource(fakeServer) {
     function ServerSideDatasource(fakeServer) {
       this.fakeServer = fakeServer;
     }
    
     ServerSideDatasource.prototype.getRows = function(params) {
       console.log("ServerSideDatasource.getRows: params = ", params);
       var rows = this.fakeServer.getData(params.request);
       setTimeout(function() {
         params.successCallback(rows, rows.length);
       }, 200);
     };
    
     return new ServerSideDatasource(fakeServer);
    }
    
  4. 实现onGridReady()

    一旦此数据源准备就绪,您必须通过调用其 API 方法将其提供给 ag-grid:params.api.setServerSideDataSource()。此 API 在 onGridReady() 方法中可用,该方法也必须传递给 Ag-grid。如果您使用的是服务器端行模型,则必须使用此方法。

    onGridReady = params => {
      ...
      var fakeServer = createFakeServer(jsonDataFromServer);
      var dataSource = createServerSideDatasource(fakeServer);
      params.api.setServerSideDatasource(dataSource);
    }
    
  5. 提供帮助 ag-grid 识别父子关系的关键属性。您必须将这些参数提供给网格。检查具有 HTML 语法的实现中的点 (1),并显示如何将这些方法提供给 ag-grid。

    var rowModelType = "serverSide";
    var isServerSideGroup = function (dataItem) {
      return !!dataItem.children;
    };
    
    var getServerSideGroupKey = function (dataItem) {
      return dataItem.employeeId;
    };
    

    请注意,在 getServerSideGroup() 中,我们返回一个布尔值,用于检查当前行的 children 属性(即 dataItem)是否有任何子项。


我会要求您分别查看每个功能的服务器端行模型的文档,这意味着树数据(客户端模型)和树数据(服务器端模型)有两种不同的方法。我们不能设置一个模型并期望它与其他模型的数据一起工作。

服务器端行模型的文档:https://www.ag-grid.com/javascript-grid-server-side-model/

请试试这个并告诉我。一个月前我有这些要求,所以我联系了他们寻求他们对试用支持的帮助,他们为此问题陈述准备了一个 plunker: 来自服务器端的具有无限滚动的树数据的工作示例。 https://next.plnkr.co/edit/XON5qvh93CpURbOJ?preview

注意:

  1. 由于是从服务器检索树数据,因此无法使用 getDataPath。
  2. 与客户端树模型不同,树数据将在每行嵌套层次结构中。因此,唯一的列名不会封装在数组中。

错了:

var rowData = [
    {orgHierarchy: ['Erica'], jobTitle: "CEO", employmentType: "Permanent"},
    {orgHierarchy: ['Erica', 'Malcolm'], jobTitle: "VP", employmentType: "Permanent"}
    ...
]

正确:

[{
    "employeeId": 101,
    ...
    "children": [
        {
        "employeeId": 102,
        ...
        "children": [
            {
            "employeeId": 103,
            ...
            },
            {
            "employeeId": 104,
            ...
            }
         ]},
    ]}
}]
  1. 当我刚刚使用 Enterprise 功能设置网格时,在初始阶段根本没有渲染网格,因此他们建议使用 px 而不是 % 作为包装器 DIV 元素的高度和宽度包含您的 Ag-grid 元素。

编辑:

  1. 如果您希望在单独的 API 调用中获取子记录以节省初始加载时间,那么您可以在 getRows() 方法中进行这些 API 调用。 API 调用将有成功和错误回调。在成功回调方法中,一旦您收到子数据,您可以使用以下方法将它们传递给 ag-grid:
      params.successCallback(childrenData, childrenData.length);

示例:当父行展开时,它会通过 params.request.groupKeys 发送该父行的唯一键(您必须已经配置)。在此示例中,我使用 JavaScript 的 fetch() 来表示 API 调用。此方法接受 ApiUrl,以及在 POST/PUT 请求的情况下可选的请求参数对象。

  ServerSideDatasource.prototype.getRows = function(params) {
    
    //get children data based on unique value of parent row from groupKeys
    if(params.request.groupKeys.length > 0) {
        fetch(API_URL, {...<required parameters>...})
        .then(response => response.json(), error => console.log(error))
        .then((childrenData) => {
            params.successCallback(childrenData, childrenData.length);
        });
    }
    else {
        //this blocks means - get the parent data as usual.
        params.successCallback(this.fakeServer.data, this.fakeServer.data.length);
    }
  };

【讨论】:

  • 我正在触发另外一个 rest api 来获取子数据,因为加载子数据需要更多时间,我无法获取 treedata。我该如何解决这个问题?
  • 嗨@RuchiGupta,如果您遵循与我在这里分享的几乎相似的代码,请查看我的编辑部分,该部分解释了如何获取子数据并将其提供给网格。否则,我建议您在这里发布一个问题,其中包含您尝试使其工作的代码。如果您有任何疑问,请询问。
【解决方案2】:
  • 确保您使用的是gridOptions.treeData = true An example is here.
  • 实现gridOptions.getDataPath(data)时应正确设置数据的层次结构
  • 确保你已经实现了Enterperise.getRowsRead more

如果上述事情不起作用,请在此处分享您的代码以更好地了解整体情况。

【讨论】:

    【解决方案3】:

    无限滚动或企业/服务器端数据源与树数据不兼容 https://www.ag-grid.com/javascript-grid-row-models/

    因此,您必须更改代码以使用客户端行模型或使用行分组(仅在企业中可用)

    【讨论】:

      【解决方案4】:

      添加import 'ag-grid-enterprise' 然后初始化企业密钥解决了getDataPath 无法正常工作的问题。

      【讨论】:

        【解决方案5】:

        使用上面 Akshay Raut 提供的示例,我受到启发,将服务器端分页和客户端分组结合起来。跟着他的脚步,微微一变。在getServerSideDatasource 函数上,您可以检查父节点是否有子节点,而不是调用服务器,直接返回子节点。这样,您将能够将已加载的子项显示为客户端。这是一个示例代码:

        getServerSideDatasource(): IServerSideDatasource {
            return {
              getRows: (params) => {
                if (params.request.groupKeys.length > 0) {
                  params.success({
                    rowData: params.parentNode.data.sales,
                    rowCount: params.parentNode.data.sales.length,
                  });
                } else {
                   // Your regular server code to get next page
               }
        

        这是一个堆栈闪电战: https://stackblitz.com/edit/ag-grid-angular-hello-world-1gs4jx?file=src%2Fapp%2Fapp.component.ts

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-12
          • 2021-04-14
          • 2017-01-28
          • 2019-06-01
          • 2020-04-04
          • 2018-09-29
          • 2020-07-03
          • 2019-11-06
          相关资源
          最近更新 更多