Search code examples
reactjsag-gridinfinite-scroll

How to select a row on ag-grid in Infinite Row mode


Many similar questions here, but I'm unable to find a solution to my basic requirement.

I'm using ag-grid in React in the Infinite Row model. Data are loaded from server by blocks of 100.

I would like to preselect a row - for example row id 500. This requires loading the right block and, once loaded, then selecting the right node.

Example here: (click on Jump to 500 button) demo code

const jumpTo500 = () => {
  if (gridApi.getInfiniteRowCount() < 501) {
    gridApi.setRowCount(501, false);
  }
  gridApi.ensureIndexVisible(500, 'middle');

  gridApi.forEachNode((node) => {
    if (node.rowIndex === 499) {
      node.setSelected(true);
    }
  });
};

Right now I need to click twice on the button because I try to select to row before the node is loaded.

Question: How to know when the grid is rendered and the new nodes are loaded?

onRowDataChanged() and onRowDataUpdated() events are never called.


Solution

  • my current workaround...

        const jumpTo500 = async () => {
          if (!gridApi) return;
    
          const node = gridApi.getModel().getRow(500);
          if (node) {
            until(() => !!node.id, 50, 5000)
                .then((ms) => {
                    console.log("ok in ", ms, "ms");
                    node.setSelected(true, false, true);
                    gridApi.ensureNodeVisible(node, "middle");
                })
                .catch((ms) => console.log("timeout after", ms, "ms"));
          }
      };
    

    I'm able to select the row once the node.id is available. Utility method until() will retry every 50ms until the condition is ok or if timeout after 5sec.

        const until = (condition: () => boolean, interval: number, timeout: number) =>
          new Promise<number>((resolve, reject) => {
            if (condition()) {
                resolve(0);
            }
            const start = new Date().getTime();
            const intervalTimer = setInterval(() => {
                const elapsed = new Date().getTime() - start;
                if (condition()) {
                    clearInterval(intervalTimer);
                    resolve(elapsed);
                } else {
                    if (elapsed >= timeout) {
                        clearInterval(intervalTimer);
                        reject(elapsed);
                    }
                }
            }, interval);
        });