nadbm / react-datasheet

Excel-like data grid (table) component for React
https://nadbm.github.io/react-datasheet/
MIT License
5.39k stars 457 forks source link

How to (programmatically) select all cells, then copy? #303

Open ericman314 opened 2 years ago

ericman314 commented 2 years ago

I will ask and answer my own question in the hopes it can be of use to someone, but I'm really hoping someone will share the right way to do this.

I have a ReactDataGrid with a controlled selection. I also have a custom copy handler, but I don't think that matters in this case.

<ReactDataGrid>
  data={myData}
  selected={mySelection}
  onSelect={setMySelection}
  handleCopy={handleCopy}
</ReactDataGrid>

I also have a "Select All" button outside of my ReactDataGrid, whose onClick handler calls this function to set the selection to the entire range:

function handleSelectAll() {
  setMySelection({ start: { i: 0, j: 0 }, end: { i: myData.length - 1, j: myData[0].length - 1 } })
} 

The problem is, after pressing the button, the "focus" in the table is lost and pressing Ctrl+C does nothing.

The only way I could get it to work was by dispatching mouse events to cells within the table, to simulate the user dragging across the entire table. This prevents the click on the "Select All" button from removing the Ctrl+C listener:

function handleSelectAll() {
  let topLeftElement = document.querySelector('table.data-grid > tbody > tr > td')
  topLeftElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))

  let bottomRightElement = document.querySelector('table.data-grid > tbody > tr:last-child > td:last-child')
  setImmediate(() => bottomRightElement.dispatchEvent(new MouseEvent('mouseover', { bubbles: true })))
  setImmediate(() => bottomRightElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })))
} 

This is a no-good, horrible, very bad hack, so if anyone knows the correct way to do this I would be very glad to see it. In any case, thanks for this great library!