Need help figuring out how custom copy / paste functionality can be implemented for multiple React Data Grid tables in a single page. As per below code, copy / paste is being triggered for both the tables.
import { connect } from 'react-redux';
import ReactDataGrid from 'fixed-react-data-grid';
const defaultParsePaste = str => str.split(/\r\n|\n|\r/).map(row => row.split('\t'));
class DataGrid extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: [],
topLeft: {},
botRight: {},
};
this.columns = [
{ key: 'col1', name: 'Col1', editable: true },
{ key: 'col2', name: 'Col2', editable: true },
{ key: 'col3', name: 'Col3', editable: true },
{ key: 'col4', name: 'Col4', editable: true },
];
}
componentDidMount() {
document.addEventListener('copy', this.handleCopy);
document.addEventListener('paste', this.handlePaste);
}
componentWillUnmount() {
document.removeEventListener('copy', this.handleCopy);
document.removeEventListener('paste', this.handlePaste);
}
rowGetter = i => {
const { rows } = this.state;
return rows[i];
};
handleCopy = e => {
e.preventDefault();
e.stopPropagation();
const { topLeft, botRight } = this.state;
// Loop through each row
const text = range(topLeft.rowIdx, botRight.rowIdx + 1)
.map(
// Loop through each column
rowIdx =>
this.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');
e.clipboardData.setData('text/plain', text);
};
handlePaste = e => {
e.preventDefault();
e.stopPropagation();
const { topLeft } = this.state;
const newRows = [];
const pasteData = defaultParsePaste(e.clipboardData.getData('text/plain'));
pasteData.forEach(row => {
const rowData = {};
// Merge the values from pasting and the keys from the columns
this.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);
});
this.updateRows(topLeft.rowIdx, newRows);
};
onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
const { rows } = this.state;
this.setState(state => {
const rows1 = state.rows.slice();
for (let i = fromRow; i <= toRow; i += 1) {
rows[i] = { ...rows[i], ...updated };
}
return { rows1 };
});
};
setSelection = args => {
console.log(args, 'setSelection');
this.setState({
topLeft: {
rowIdx: args.topLeft.rowIdx,
colIdx: args.topLeft.idx,
},
botRight: {
rowIdx: args.bottomRight.rowIdx,
colIdx: args.bottomRight.idx,
},
});
};
render() {
return (
<div>
<ReactDataGrid
columns={this.columns}
rowGetter={i => this.state.rows[i]}
rowsCount={this.state.rows.length}
onGridRowsUpdated={this.onGridRowsUpdated}
enableCellSelect
minColumnWidth={40}
cellRangeSelection={{
onComplete: this.setSelection,
}}
onCellSelected={s => this.setSelection({ topLeft: s, bottomRight: s })}
/>
</div>
);
}
}
export default connect(
null,
null,
)(DataGrid);
The above DataGrid component is being imported in the parent component 2 times to solve a business case.
Few methods that I tried -
- Tried creating a ref -
<div ref={el => this.wrapperRef = el}>
and added the event listener to the ref likethis.wrapperRef.addEventListener('copy', this.handleCopy)
but then thehandleCopy
function is not being called. - Tried
<div onCopy={this.handleCopy}
but thehandleCopy
function is not being called.