In this article we explore ways to dynamically edit all cells selected in a range as shown in this plunkr
How does it work?
const [shouldBatchUpdate, setShouldBatchUpdate] = useState(false);
const [updatedBatch, setUpdatedBatch] = useState({ startRowIndex: 0, endRowIndex: 0, colIds: [], gridApi: null, }); const editValueRef = useRef('');
const [rowData, setRowData] = useState(getData()); const [columnDefs] = useState([ { field: 'athlete' }, { field: 'country' }, { field: 'age' }, { field: 'year' }, { field: 'sport' }, ]);
Above are all the state variables we need for this example, the ones to note down are:
- shouldBatchUpdate - is a flag we set to true when we have updated the batch
- updatedBatch - an object which tells the grid:
-
-
-
-
- startRowIndex - where to start editing
- endRowIndex - where to end editing
- colIds - which columns to edit
- gridApi - takes the grid api we need to call after setting new rowData
-
-
-
-
- editValueRef - a React Ref needed to hold our new edited value.
const onSuppressKeyboardEvent = (params) => { let isCtrlKey = params.event.ctrlKey; let isEnterKey = params.event.key === 'Enter'; let isEditing = params.editing; if (isEditing) { if (isCtrlKey && isEnterKey) { params.api.getCellRanges().forEach((range) => { let colIds = range.columns.map((col) => col.colId); let startRowIndex = Math.min( range.startRow.rowIndex, range.endRow.rowIndex ); let endRowIndex = Math.max( range.startRow.rowIndex, range.endRow.rowIndex ); setUpdatedBatch({ startRowIndex, endRowIndex, colIds, gridApi: params.api, }); }); setShouldBatchUpdate(true); } } };
First, we leverage a column callback function provided by the grid - onSuppressKeyboardEvent, this allows us to suppress default keyboard events.
We then run a check to see if the cell is being edited (isEditing) - If so, has the Ctrl + Enter key been pressed?
Yes, we map over the all the columns that have been selected (if any) and store their id in an array - now we know which columns we're going to edit.
The api call getCellRanges also gives us the startRowIndex & endRowIndex of selected cells. we use Math.min & Math.max to account for users who may start their selection bottom - up.
Now we have our startRowIndex, endRowIndex, colIds & gridApi (taken from params) we setUpdatedBatch state & change our flag to true with setShouldBatchUpdate
Note: Pressing Enter ends the editing so we wired up the Ctrl key to tell the grid we want all highlighted cells to update with this value.
const onCellEditingStopped = (params) => { editValueRef.current = params.newValue; if (shouldBatchUpdate) { const { startRowIndex, endRowIndex, colIds, gridApi } = updatedBatch; editSelectedCells( startRowIndex, endRowIndex, colIds, gridApi, editValueRef.current ); setShouldBatchUpdate(false); } };
We use an Editing Event provided by the grid, onCellEditingStopped to detect the user has stopped editing and update our editValueRef with the newValue provided in our params.
With shouldBatchUpdate being true we pass all relevant arguments to our editSelectedCells function below:
const editSelectedCells = (start, end, columns, gridApi, value) => { let rowIds = {}; // only update rows that ids exists within this obj for (let i = start; i <= end; i++) { let rowId = gridApi.rowModel.rowsToDisplay[i].id; rowIds[rowId] = true; } setRowData((prevRowData) => prevRowData.map((row) => { if (!rowIds[row.id]) return row; let newRow = { ...row }; columns.forEach((colId) => { newRow[colId] = value; }); return newRow; }) ); };
Comments
0 comments
Please sign in to leave a comment.