4

I'm using the grid api to get the selected rows by using the function getSelectedRows(). However, the list of rows seems to be unordered, i.e the items are not in the order I selected them in.

Is there another way to get the selected rows in the order they were selected?

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
tbr
  • 43
  • 4

1 Answers1

2

You can keep track of the selected items yourself and make sure it's chronologically ordered by listening to selectionChanged event.

// global keyboard state, put this outside of the function body
// we need to store the current shift key state to know if user
// are selecting multiple rows
const KEYBOARD_STATE = {
  isShiftPressed: false
};
document.addEventListener("keydown", (e) => {
  KEYBOARD_STATE.isShiftPressed = e.key === "Shift";
});
document.addEventListener("keyup", (e) => {
  KEYBOARD_STATE.isShiftPressed = false;
});
const [selection, setSelection] = React.useState([]);
const onSelectionChanged = (e) => {
  const selectedNodes = e.api.getSelectedNodes();
  const lastSelectedNode =
    selectedNodes[0]?.selectionController?.lastSelectedNode;
  // if lastSelectedNode is missing while multi-selecting,
  // AgGrid will select from the first row
  const selectedNodeFrom = lastSelectedNode || e.api.getRenderedNodes()[0];
  const isRangeSelect = KEYBOARD_STATE.isShiftPressed;
  const difference = (arr1, arr2) => arr1.filter((x) => !arr2.includes(x));
  const newSelection = difference(selectedNodes, selection);

  if (newSelection.length > 0) {
    if (isRangeSelect) {
      const isSelectBackward =
        newSelection[0].rowIndex < selectedNodeFrom.rowIndex;

      if (isSelectBackward) {
        newSelection.reverse();
      }
    }

    newSelection.forEach((n) => updateSelection(n));
  } else {
    updateSelection(); // deselect
  }
};
const updateSelection = (rowNode) => {
  setSelection((selections) => {
    if (rowNode) {
      const isSelected = rowNode.isSelected();

      if (isSelected) {
        return [...selections, rowNode];
      } else {
        return selections.filter((s) => s.id !== rowNode.id);
      }
    } else {
      return selections.filter((n) => n.isSelected());
    }
  });
};
return (
  <>
    <pre>
      {JSON.stringify(selection.map((n) => n.data.id))}
    </pre>
    <AgGridReact
      rowSelection="multiple"
      columnDefs={columnDefs}
      rowMultiSelectWithClick
      onSelectionChanged={onSelectionChanged}
      {...}
    />
  </>
);

Live Demo

Edit 63988970/how-to-get-the-selection-order-in-ag-grid/63990845#63990845

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
  • Thank you for your answer. This works well when multiple rows are selected by clicking or by using the ctrl-key. However, if I for instance, select a row at index 8, and then hold down the shift key and select a row at index 4, the selection will be: [8,4,5,6,7]. I was expecting: [8,7,6,5,4], since I started the selection on a higher index and ended the selection at a lower index. This is reproducible in your example. Do you know how to solve this particular problem? – tbr Sep 22 '20 at 07:42
  • @terjebra I've updated my answer and the demo to take into account of range selection. – NearHuscarl Sep 22 '20 at 11:29
  • Thank you. This was exactly was I was looking for. – tbr Sep 22 '20 at 13:44
  • You're welcome @terjebra. If you find this answer or any other answers helpful to you, please consider upvoting them. Thank you. – NearHuscarl Sep 22 '20 at 13:52