-
-
Save ZackKnopp/40fc0691feb03f0fba3e25e7353b73ae to your computer and use it in GitHub Desktop.
// Fix for copy cell in react-data-grid showing up | |
.react-grid-cell-copied { | |
display: none; | |
} |
// Tested with react-data-grid v5.0.4, earlier versions MAY NOT HAVE cellRangeSelection | |
// And it won't show any errors if you try this with an earlier version, so use at least v5.0.4 | |
import React, { Component } from 'react'; | |
import { range } from 'lodash'; | |
import ReactDataGrid from 'react-data-grid'; // Tested with v5.0.4, earlier versions MAY NOT HAVE cellRangeSelection | |
const columns = [ | |
{ key: 'id', name: 'ID', editable: true }, | |
{ key: 'title', name: 'Title', editable: true }, | |
{ key: 'count', name: 'Complete', editable: true }, | |
{ key: 'sarah', name: 'Sarah', editable: true }, | |
{ key: 'jessica', name: 'Jessica', editable: true }, | |
]; | |
const initialRows = Array.from(Array(1000).keys(), (_, x) => ( | |
{ id: x, title: x * 2, count: x * 3, sarah: x * 4, jessica: x * 5 } | |
)); | |
const defaultParsePaste = str => ( | |
str.split(/\r\n|\n|\r/) | |
.map(row => row.split('\t')) | |
); | |
class MyDataGrid extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
rows: initialRows, | |
topLeft: {}, | |
botRight: {}, | |
}; | |
// Copy paste event handler | |
document.addEventListener('copy', this.handleCopy); | |
document.addEventListener('paste', this.handlePaste); | |
} | |
componentWillUnmount() { | |
this.removeAllListeners(); | |
} | |
removeAllListeners = () => { | |
document.removeEventListener('copy', this.handleCopy); | |
document.removeEventListener('paste', this.handlePaste); | |
} | |
rowGetter = (i) => { | |
const { rows } = this.state; | |
return rows[i]; | |
} | |
updateRows = (startIdx, newRows) => { | |
this.setState((state) => { | |
const rows = state.rows.slice(); | |
for (let i = 0; i < newRows.length; i++) { | |
if (startIdx + i < rows.length) { | |
rows[startIdx + i] = { ...rows[startIdx + i], ...newRows[i] }; | |
} | |
} | |
return { rows }; | |
}); | |
} | |
handleCopy = (e) => { | |
console.debug('handleCopy Called'); | |
e.preventDefault(); | |
const { topLeft, botRight } = this.state; | |
// Loop through each row | |
const text = range(topLeft.rowIdx, botRight.rowIdx + 1).map( | |
// Loop through each column | |
rowIdx => columns.slice(topLeft.colIdx, botRight.colIdx + 1).map( | |
// Grab the row values and make a text string | |
col => this.rowGetter(rowIdx)[col.key], | |
).join('\t'), | |
).join('\n'); | |
console.debug('text', text); | |
e.clipboardData.setData('text/plain', text); | |
} | |
handlePaste = (e) => { | |
console.debug('handlePaste Called'); | |
e.preventDefault(); | |
const { topLeft } = this.state; | |
const newRows = []; | |
const pasteData = defaultParsePaste(e.clipboardData.getData('text/plain')); | |
console.debug('pasteData', pasteData); | |
pasteData.forEach((row) => { | |
const rowData = {}; | |
// Merge the values from pasting and the keys from the columns | |
columns.slice(topLeft.colIdx, topLeft.colIdx + row.length) | |
.forEach((col, j) => { | |
// Create the key-value pair for the row | |
rowData[col.key] = row[j]; | |
}); | |
// Push the new row to the changes | |
newRows.push(rowData); | |
}); | |
console.debug('newRows', newRows); | |
this.updateRows(topLeft.rowIdx, newRows); | |
} | |
onGridRowsUpdated = ({ fromRow, toRow, updated, action }) => { | |
console.debug('onGridRowsUpdated!', action); | |
console.debug('updated', updated); | |
if (action !== 'COPY_PASTE') { | |
this.setState((state) => { | |
const rows = state.rows.slice(); | |
for (let i = fromRow; i <= toRow; i++) { | |
rows[i] = { ...rows[i], ...updated }; | |
} | |
return { rows }; | |
}); | |
} | |
}; | |
setSelection = (args) => { | |
this.setState({ | |
topLeft: { | |
rowIdx: args.topLeft.rowIdx, | |
colIdx: args.topLeft.idx, | |
}, | |
botRight: { | |
rowIdx: args.bottomRight.rowIdx, | |
colIdx: args.bottomRight.idx, | |
}, | |
}); | |
}; | |
render() { | |
const { rows } = this.state; | |
return ( | |
<div> | |
<ReactDataGrid | |
columns={columns} | |
rowGetter={i => rows[i]} | |
rowsCount={rows.length} | |
onGridRowsUpdated={this.onGridRowsUpdated} | |
enableCellSelect | |
minColumnWidth={40} | |
cellRangeSelection={{ | |
onComplete: this.setSelection, | |
}} | |
/> | |
</div> | |
); | |
} | |
} | |
export default MyDataGrid; |
Thanks you so much
Issue when using cellRangeSelection
adazzle/react-data-grid#1460
@ykrsm thanks for the link to the issue
I am using the react data grid version 6.0.10 but still getting the error for the attribute cellRangeSelection and the error is Property 'cellRangeSelection' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes and second issue is when I am trying to copy cells inside the grid .I am not able do it.
Thanks in advance for your help.
Will it work if we are using latest version of react data grid 7.0.0-canary.30 ?
doesn't seem like it, i'm having a hell of a time getting what feels like basic "data grid" functionality on the new 7.0.0-beta-16. I just want to copy and paste to/from like any other application. Not sure why cell selection was removed, or why the onPaste
handler only gets called seemingly after something has been copied from INSIDE the grid component. Going beyond beta 16 hilariously and frustratingly screws up the entire grid styling such that it no longer looks anything like a grid component.
You, sir, are a hero. Thank you so much.