Column and row reordering
To enable row or column reordering in ReactGrid, the following props need to be passed to the component:
- For row reordering:
enableRowSelectionOnFirstColumn?: boolean;
onRowReorder?: (selectedRowIndexes: number[], destinationRowIdx: number) => void;
- For column reordering:
enableColumnSelectionOnFirstRow?: boolean;
onColumnReorder?: (selectedColIndexes: number[], destinationColIdx: number) => void;
Live example
Code
const peopleData = [ { id: "66d61077035753f369ddbb16", name: "Jordan Rodriquez", age: 30, email: "jordanrodriquez@cincyr.com", company: "Zaggles", position: 1, }, { id: "66d61077794e7949ab167fd5", email: "allysonrios@satiance.com", name: "Allyson Rios", age: 30, company: "Zoxy", position: 2, }, { id: "66d61077dd754e88981ae434", name: "Pickett Lucas", age: 25, email: "pickettlucas@zoxy.com", company: "Techade", position: 3, }, { id: "66d61077115e2f8748c334d9", name: "Louella David", age: 37, email: "louelladavid@techade.com", company: "Ginkogene", position: 4, }, { id: "66d61077540d53374b427e4b", name: "Tricia Greene", age: 27, email: "triciagreene@ginkogene.com", company: "Naxdis", position: 5, }, ]; const cellStyles = { header: { backgroundColor: "#55bc71", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", }, }; const getRows = (people: Person[]): Row[] => [ // header row { rowIndex: 0, height: 40, reorderable: false, }, // data rows ...people.map((_, i) => ({ rowIndex: i + 1, height: 40, })), ]; type ColumnDef = { colIndex: number; width: string | number; title: string; minWidth?: string | number; resizable?: boolean; reorderable?: boolean; }; // Columns with fields 'title' will be used for column reordering const getColumns = (): ColumnDef[] => [ { colIndex: 0, width: 220, title: "Name" }, { colIndex: 1, width: 220, title: "Age" }, { colIndex: 2, width: 220, title: "Email" }, { colIndex: 3, width: 220, title: "Company" }, ]; const handleRowReorder = ( peopleData: Person[], selectedRowIndexes: number[], destinationRowIdx: number, updatePerson: (id: string, key: string, newValue: number) => void ) => { const prevPeopleData = [...peopleData].sort((a, b) => a.position - b.position); // Adjust the destination index to account for the header row const adjustedDestinationIdx = destinationRowIdx - 1; const adjustedSelectedRowIdxs = selectedRowIndexes.map((rowIdx) => rowIdx - 1); const isReorderingUpwards = adjustedSelectedRowIdxs.some((rowIdx) => rowIdx > adjustedDestinationIdx); adjustedSelectedRowIdxs.forEach((rowIdx, index) => { if (adjustedDestinationIdx === 0) { prevPeopleData[rowIdx].position = prevPeopleData[adjustedDestinationIdx].position / 2 + index * 0.0001; } else if (adjustedDestinationIdx === peopleData.length - 1) { prevPeopleData[rowIdx].position = prevPeopleData[adjustedDestinationIdx].position + 1 + index * 0.0001; } else if (isReorderingUpwards) { prevPeopleData[rowIdx].position = (prevPeopleData[adjustedDestinationIdx].position + prevPeopleData[adjustedDestinationIdx - 1].position) / 2 + index * 0.0001; } else { prevPeopleData[rowIdx].position = (prevPeopleData[adjustedDestinationIdx].position + prevPeopleData[adjustedDestinationIdx + 1].position) / 2 + index * 0.0001; } }); prevPeopleData.forEach((row) => { updatePerson(row.id, "position", row.position); }); }; const handleColumnReorder = ( selectedColIndexes: number[], destinationColIdx: number, setColumns: React.Dispatch<React.SetStateAction<ColumnDef[]>> ) => { setColumns((prevColumns) => { // Filter out the selected columns and unselected columns const selectedColumns = prevColumns.filter((_, index) => selectedColIndexes.includes(index)); const unselectedColumns = prevColumns.filter((_, index) => !selectedColIndexes.includes(index)); // Adjust the destination index based on the direction of the reorder const adjustedDestinationColIdx = selectedColIndexes[0] > destinationColIdx ? destinationColIdx : destinationColIdx - selectedColumns.length + 1; // Create the new columns array with reordered columns const newColumns = [ ...unselectedColumns.slice(0, adjustedDestinationColIdx), ...selectedColumns, ...unselectedColumns.slice(adjustedDestinationColIdx), ]; return newColumns; }); }; type UpdatePerson = <T>(id: string, key: string, newValue: T) => void; const generateCells = (people: Person[], columns: ColumnDef[], updatePerson: UpdatePerson): Cell[] => { const generateHeaderCells = () => { return columns.map((column, colIdx) => ({ rowIndex: 0, colIndex: colIdx, Template: NonEditableCell, props: { value: column.title, style: cellStyles.header, }, })); }; const generateRowCells = (rowIndex: number, person: Person): Cell[] => { const { id, name, age, email, company } = person; const nameColIndex = columns.findIndex((col) => col.title === "Name"); const ageColIndex = columns.findIndex((col) => col.title === "Age"); const emailColIndex = columns.findIndex((col) => col.title === "Email"); const companyColIndex = columns.findIndex((col) => col.title === "Company"); return [ { rowIndex, colIndex: nameColIndex, Template: TextCell, props: { text: name, onTextChanged: (newText: string) => updatePerson(id, "name", newText), }, }, { rowIndex, colIndex: ageColIndex, Template: NumberCell, props: { value: age, onValueChanged: (newValue: number) => updatePerson(id, "age", newValue), }, }, { rowIndex, colIndex: emailColIndex, Template: TextCell, props: { text: email, onTextChanged: (newText: string) => updatePerson(id, "email", newText), }, }, { rowIndex, colIndex: companyColIndex, Template: TextCell, props: { text: company, onTextChanged: (newText: string) => updatePerson(id, "company", newText), }, }, ]; }; people.sort((a, b) => a.position - b.position); const headerCells = generateHeaderCells(); const rowCells = people.flatMap((person, idx) => generateRowCells(idx + 1, person)); return [...headerCells, ...rowCells]; }; const ReactGridExample = () => { const [people, setPeople] = useState(peopleData); const updatePerson = (id, key, newValue) => { setPeople((prev) => { return prev.map((p) => (p.id === id ? { ...p, [key]: newValue } : p)); }); }; const rows = getRows(people); const [columns, setColumns] = useState(getColumns()); const cells = generateCells(people, columns, updatePerson); return ( <div> <ReactGrid rows={rows} columns={columns} cells={cells} enableRowSelectionOnFirstColumn enableColumnSelectionOnFirstRow onRowReorder={(selectedRowIndexes, destinationRowIdx) => handleRowReorder(people, selectedRowIndexes, destinationRowIdx, updatePerson) } onColumnReorder={(selectedColIndexes, destinationColIdx) => handleColumnReorder(selectedColIndexes, destinationColIdx, setColumns) } /> </div> ); }; render(<ReactGridExample />, document.getElementById("root"));
Preview