Reputation: 1578
I have a working version of Tanstack Table in React.js that lets me drag and drop to re-order rows one at a time. https://codesandbox.io/p/sandbox/table-test-forked-7htfr5?workspaceId=ws_F2QxELJDBKDDSAxdPEPbQt
I am trying to add the row selection feature they have demonstrated online here: https://tanstack.com/table/v8/docs/framework/react/examples/row-selection
I have tried my own version of implementing the row-selection logic into my first link working drag and drop codesandbox, but the behavior is wrong, as the user is only allowed to drag and drop one row, before the feature becomes broken and stops working: https://codesandbox.io/p/sandbox/table-test-forked-t8xtqr?workspaceId=ws_F2QxELJDBKDDSAxdPEPbQt
Can someone help me add the checkmark row selection row to my working drag and drop table below? Thanks App.js:
import "./styles.css";
import Table from "./Table.js"; // Adjust the path as necessary
import { arrayMove } from "@dnd-kit/sortable";
import { useState } from "react";
export default function App() {
const [testData, setTestData] = useState([
{ id: "a1", fileName: "Test Audio 1", duration: "2:30" },
{ id: "a2", fileName: "Test Audio 2", duration: "3:45" },
{ id: "a3", fileName: "Test Audio 3", duration: "4:15" },
]);
const testColumns = [
{ accessorKey: "draggable", header: "Drag" },
{ accessorKey: "fileName", header: "File Name" },
{ accessorKey: "duration", header: "Duration" },
];
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Table
data={testData}
setData={(oldData, active, over) => {
const oldIndex = oldData.findIndex((row) => row.id === active.id);
const newIndex = oldData.findIndex((row) => row.id === over.id);
if (oldIndex !== -1 && newIndex !== -1) {
const newData = arrayMove(oldData, oldIndex, newIndex);
setTestData(newData);
}
}}
columns={testColumns}
/>
</div>
);
}
Table.js:
// https://tanstack.com/table/v8/docs/framework/react/examples/row-selection
import React from "react";
import {
ColumnDef,
getCoreRowModel,
useReactTable,
flexRender,
} from "@tanstack/react-table";
import { DndContext, closestCenter } from "@dnd-kit/core";
import {
arrayMove,
SortableContext,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import styles from "./Table.module.css";
// Drag handle for rows
function DragHandle({ row }) {
const { attributes, listeners } = useSortable({ id: row.original.id });
return (
<button
{...attributes}
{...listeners}
className={styles.dragHandle}
title="Drag to reorder"
>
🟰
</button>
);
}
// Row Component
function Row({ row }) {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({
id: row.original.id,
});
const style = {
transform: CSS.Transform.toString(transform),
transition,
};
return (
<tr
ref={setNodeRef}
style={style}
{...attributes}
{...listeners}
className={styles.row}
>
{row.getVisibleCells().map((cell, index) => (
<td key={cell.id} className={styles.cell}>
{index === 0 ? <DragHandle row={row} /> : null}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
);
}
// Table Component
function Table({ data, setData, columns }) {
const tableColumns = React.useMemo(() => [...columns], [columns]);
const table = useReactTable({
data,
columns: tableColumns,
getCoreRowModel: getCoreRowModel(),
});
const handleDragEnd = (event) => {
const { active, over } = event;
if (!active?.id || !over?.id || active.id === over.id) {
return;
}
setData(data, active, over);
};
return (
<DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<SortableContext
items={data.map((row) => row.id)}
strategy={verticalListSortingStrategy}
>
<table className={styles.table}>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id} className={styles.headerRow}>
{headerGroup.headers.map((header) => (
<th key={header.id} className={styles.headerCell}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<Row key={row.id} row={row} />
))}
</tbody>
</table>
</SortableContext>
</DndContext>
);
}
export default Table;
Upvotes: 1
Views: 275
Reputation: 738
Here's an example with working row selection and drag and drop: https://codesandbox.io/p/sandbox/broken-row-selection-forked-93vdlc?workspaceId=ws_Ugp8jRneUmKth2oi4rosAj
I manually placed the DragHandle in the return of the Row
since it seemed to break when rendered by flexRender, not sure why.
<td key={cell.id} className={styles.cell}>
{index === 1 ? <DragHandle row={row} /> : null}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
Upvotes: 0