Как реализовать переупорядочение нескольких строк перетаскиванием в компоненте таблицы React TanStack?CSS

Разбираемся в CSS
Ответить Пред. темаСлед. тема
Anonymous
 Как реализовать переупорядочение нескольких строк перетаскиванием в компоненте таблицы React TanStack?

Сообщение Anonymous »

У меня есть реагирующий компонент Table.js, который имеет возможность выбирать строки и перетаскивать их, чтобы изменить порядок отдельных строк:
https://codesandbox.io/p/sandbox/working-row-selecton- reorder-add-pagination-search-col-sort-forked-7y95lv?workspaceId=ws_F2QxELJDBKDDSAxdPEPbQt
В некоторых случаях у моего пользователя могут быть сотни файлов, и он хочет изменить порядок группы из 20 строк. Текущий процесс изменения порядка каждой строки вручную очень утомителен, я хочу добавить пользователю возможность перетаскивания и удалить сразу несколько строк, переупорядочив их все.
Я нашел хороший пост о UX с изображениями о том, как это можно сделать, и хочу попробовать реализовать его в мой React Table.js компонент:
https://ux.stackexchange.com/questions/ ... ble-and-be -able-to-reorder-the-selec
Итак, если пользователь выбирает несколько строк:
Изображение

Они могут перетаскиваться, чтобы изменить порядок всех текущих выбранных строк с помощью специального всплывающего окна пользовательского интерфейса слева. таблицы:
Изображение

В настоящее время находится в мой codeandbox.io пользователь может выбрать несколько файлов и всегда изменять порядок только одной строки за раз:
Изображение

Я попробовал реализовать это здесь:
https://codesandbox.io/p/sandbox/drag-a ... SAxdPEPbQt
Но есть в пользовательском интерфейсе нет индикации призрачных строк о том, сколько строк я переупорядочиваю, что делает процесс неинтуитивным и неясным:
//Table.js
// Table.js
import React, { useState } from "react";
import {
ColumnDef,
getCoreRowModel,
useReactTable,
flexRender,
getSortedRowModel,
getFilteredRowModel,
getPaginationRowModel,
} from "@tanstack/react-table";
import { DndContext, closestCenter } from "@dnd-kit/core";
import {
useSortable,
SortableContext,
verticalListSortingStrategy,
arrayMove,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import styles from "./Table.module.css";

// Indeterminate Checkbox Component
function IndeterminateCheckbox({ indeterminate, className = "", ...rest }) {
const ref = React.useRef(null);

React.useEffect(() => {
if (typeof indeterminate === "boolean") {
ref.current.indeterminate = indeterminate;
}
}, [indeterminate]);

return (

);
}

// Drag handle for rows
function DragHandle({ row }) {
const { attributes, listeners } = useSortable({ id: row.original.id });

return (

🟰

);
}

// Row Component
function Row({ row }) {
const { setNodeRef, transform, transition } = useSortable({
id: row.original.id,
});

const isSelected = row.getIsSelected();

const style = {
transform: CSS.Transform.toString(transform),
transition,
backgroundColor: isSelected ? "#e0f7fa" : "inherit", // Highlight selected rows
};

return (

{row.getVisibleCells().map((cell, index) => (

{index === 1 ? : null}
{flexRender(cell.column.columnDef.cell, cell.getContext())}

))}

);
}

// Table Component
function Table({ data, setData, columns, rowSelection, setRowSelection }) {
const [globalFilter, setGlobalFilter] = useState("");
const [sorting, setSorting] = useState([]);

const tableColumns = React.useMemo(() => [
{
id: "select",
header: ({ table }) => (

),
cell: ({ row }) => (



),
},
{ accessorKey: "draggable", header: "Drag" },
{ accessorKey: "fileName", header: "File Name" },
{ accessorKey: "duration", header: "Duration" },
]);

const table = useReactTable({
data,
columns: tableColumns,
getRowId: (row) => row.id,
state: { rowSelection, globalFilter, sorting },
onRowSelectionChange: setRowSelection,
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});

const handleDragEnd = (event) => {
const { active, over } = event;

if (active && over && active.id !== over.id) {
// Get the IDs of all selected rows
const selectedRowIds = Object.keys(rowSelection).filter(
(id) => rowSelection[id]
);

if (selectedRowIds.length > 0) {
// Find the indices of the selected rows
const selectedRows = data.filter((item) =>
selectedRowIds.includes(item.id)
);
const otherRows = data.filter(
(item) => !selectedRowIds.includes(item.id)
);

// Determine the target index in `otherRows` where the first selected row is dropped
const targetIndex = otherRows.findIndex((item) => item.id === over.id);

// Rebuild the data array with the selected rows inserted at the target index
const newData = [
...otherRows.slice(0, targetIndex),
...selectedRows,
...otherRows.slice(targetIndex),
];

setData(newData);
} else {
// Single row drag and drop
const oldIndex = data.findIndex((item) => item.id === active.id);
const newIndex = data.findIndex((item) => item.id === over.id);

if (oldIndex !== -1 && newIndex !== -1) {
const newData = arrayMove([...data], oldIndex, newIndex);
setData(newData);
}
}
}
};

return (

setGlobalFilter(e.target.value)}
placeholder="Search..."
className={styles.search}
/>

row.id)}
strategy={verticalListSortingStrategy}
>


{table.getHeaderGroups().map((headerGroup) => (

{headerGroup.headers.map((header) => (
header.column.toggleSorting()
: undefined
}
>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" ? " 🔼" : ""}
{header.column.getIsSorted() === "desc" ? " 🔽" : ""}

))}

))}


{table.getRowModel().rows.map((row) => (

))}




table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous


Page {table.getState().pagination.pageIndex + 1} of{" "}
{table.getPageCount()}

table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next





{Object.keys(rowSelection).length} of {data.length} rows selected



);
}

export default Table;



Подробнее здесь: https://stackoverflow.com/questions/793 ... k-table-co
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «CSS»