AG-Grid:refreshCells() & applyTransaction()。相同的 rowNodes 数组。一个有效,另一个无效?

AG-Grid: refreshCells() & applyTransaction(). Same rowNodes Array. One works, other doesn't?

一些背景:

所有,让我稍微解释一下我们如何在这里使用 ag-grid,看看这是否有助于我们找到答案。

我们的应用程序使用 Chrome 或 Edge 的本地存储。这使我们能够轻松获得大量可用数据,但确实面临着相当大的挑战。

例如,如果用户更新其网格中某个字段的值,我们需要将该更新更新到:

  1. 用户的本地存储
  2. 服务器
  3. 将更新推送给用户组织中的所有其他用户

发生这种同步,然后我们终于看到下面的代码。

此外,我们允许用户在系统的多个位置更新数据,例如使用下图:

用户可以自己更新行(北部、南部、东部和西部区域),或者他们可以单击 Tower 12 South 或 Organization Alpha 并在模式中更新这些名称或其他信息。

注意:在此网格中,Tower 12 South 和 Organization Alpha 确实是行分组。它们也是独立的数据位,可以在应用程序的其他地方进行操作。本质上它们是与此处的数据行相关的数据。

当有人点击说“Organization Alpha”并更新其名称时,下面的代码会被触发。

我们试图解决的主要问题 是在有人更新 Organization Alpha 或 Tower 12 South 上的名称后让网格重新组合并正确重绘。我们需要让网格更新更新的行分组下面的子项,以便行分组可以重新绘制,我们可以相应地显示正确的名称。

推荐之前:简单刷新clientsiderowmodel是行不通的。它用旧的网格数据刷新。我们必须在执行任何操作之前应用更新。

更新:

我尝试过使用这两种方法来应用事务、使用节点 ID 和使用 RowNode 对象。两种方式都会产生相同的结果,即使调试器显示我正在合法地传递良好的对象或 ID。

原文post:

我很难理解为什么在我们应用程序的这个特定实例中,ag-grid 不想允许行节点数组上的行事务,但允许我在 相同的行节点数组.

我得到的错误(我尝试更新的每个节点)如下:

clientSideNodeManager.js:181 ag-Grid: could not find row id=undefined, data item was not found for this id

最初,我从表面上看这个错误,并认为我的其余代码可能会乱序执行,并且我作为参数传递的节点可能确实未定义。我更进一步,简单地在 setTimeout 中设置对 applyTransaction() 的调用,以仔细检查事情是否相应地运行。那里没有运气。我启动了一个调试器并使用了控制台来确保事情按要求的顺序触发。到目前为止一切似乎都很好。

下面是我关注的部分代码。本质上,我从一个不同的函数返回一个 rowNode,并且需要更新该行节点下的所有叶子节点。很简单。

我的问题是,为什么 refreshCells 方法有效,但 applyTransaction 方法不适用于传递给它的完全相同的 rowNodes?我知道您不能将行组传递给 applyTransaction 方法,这就是为什么我只需要更新子项。有谁知道为什么这不起作用?

//self=this by the way. Set earlier in function.

this.traverseTree(doc).then((res)=>{

  console.log(res); //Shows the correct row group
  console.log(res.allLeafChildren); //Shows all leaf children
              
  setTimeout(() => {
    if(res.allLeafChildren.length > 0) {

      //Below function fires. Cells actually refresh
      self.gridOptions.api.refreshCells({rowNodes: res.allLeafChildren, force: true});

      //Will not apply transaction on same rowNodes. returns error above for each node
      self.gridOptions.api.applyTransaction({update: res.allLeafChildren});
    }
  },10);
});

我们正在使用 Angular 10 和 Ag-Grid 版本 24.0.0

我最终发现的是:

根据Ag-Grid,有两种类型的引用。直接节点 ID 引用和节点数据对象引用。

无论出于何种原因,节点 ID 更新方法都不起作用。所以在我上面的问题中,我转向了对象引用更新方法。

但是,网格似乎需要一个新对象才能真正正确地知道我们要引用的行。

最终对我有用的是从本地存储 (indexedDB) 获取新的数据集。我仍然不知道为什么使用 res.allLeafChildren 不起作用,即使它是相同的数据集。

this.traverseTree(doc).then((res) => {
  // debugger;
  let trans = [];
  let childDocType = res.allLeafChildren[0].data.docType;
  let projectID = res.allLeafChildren[0].data.exopp_equiprojects_id_c;

  let optionFilter = {
    filters: {
      exopp_equiprojects_id_c: {
        value: projectID,
        operator: '=',
        type: 'string'
      }
    }
  };

  let tempArr = [];
  let delArr = [];

  if(projectID === self.projectContextId){ 
    //Here is where I'm getting the new dataset. Which returns the EXACT same data as res.allLeafChildren....
    this.utils.getLocalDoc(childDocType, optionFilter).pipe(take(1)).toPromise().then((res) => {
      Object.keys(res.docs).forEach(doc => {
        tempArr.push(res.docs[doc]);
      });
      Object.keys(tempArr).forEach(doc => {
        //If doc is deleted
        if(tempArr[doc].deleted === 1 || tempArr[doc].deleted === '1') {
          delArr.push(tempArr[doc]);
        } else {
          trans.push(tempArr[doc]);
        }
      });

      if(delArr.length > 0) self.gridOptions.api.applyTransactionAsync({remove: delArr});
      // debugger;
      self.gridOptions.api.applyTransactionAsync({update: trans});
      self.gridOptions.api.refreshCells({rowNodes: trans, force: true});
    });
  }
});

现在我明白了,我可以做的另一件事是看看是否使用 JSON.parse(JSON.stringify(res.allLeafChildren)) 之类的东西,看看是否也能解决问题/让我不必查询 indexedDb。

总之,只要注意这个问题。这个问题和答案位于不同的网格函数中,该函数与 GraphQL

协调的数据进行通信

在 AG Grid API 中,refreshCells()applyTransaction() 的参数不同。在 refreshCells, we provide an array of RowNode objects. In applyTransaction 中,我们提供了一个行数据对象数组。

在您的代码片段中,res.allLeafChildren returns 一个 RowNode 对象数组,这就是 self.gridOptions.api.refreshCells() 起作用的原因。但是要使 self.gridOptions.api.applyTransaction() 正常工作,您需要像

这样的东西
self.gridOptions.api.applyTransaction({ update: res.allLeafChildren.map(node => node.data) });