如何集成 React-Beautiful-DND 和 Ant Design 表?
我正在尝试集成 React-Beautiful-DND 和 Ant Design 表,但在拖动行时遇到行问题。他们的风格在变化,整个桌子都在跳动。以前有人尝试过这个吗?如何保持被拖动行的样式与未拖动时的样式相同? 任何想法将不胜感激。
这是 链接到完整的沙箱。
可以看到,如果拖动任意行,表格就会跳转。
这是链接中的完整代码:
import React, { useState } from "react";
import { Table, Row, Col, Card, Empty } from "antd";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import { mutliDragAwareReorder } from "./utils";
import "./style.css";
const entitiesMock = {
tasks: [
{ id: "0", title: "Very long task title" },
{ id: "1", title: "Task 1" },
{ id: "2", title: "Task 2" },
{ id: "3", title: "Task 3" },
{ id: "4", title: "Task 4" },
{ id: "5", title: "Task 5" },
{ id: "6", title: "Task 6" },
{ id: "7", title: "Task 7" },
{ id: "8", title: "Task 8" },
{ id: "9", title: "Task 9" },
{ id: "10", title: "Task 10" },
{ id: "11", title: "Task 11" },
{ id: "12", title: "Task 12" },
{ id: "13", title: "Task 13" },
{ id: "14", title: "Task 14" },
{ id: "15", title: "Task 15" },
{ id: "16", title: "Task 16" },
{ id: "17", title: "Task 17" },
{ id: "18", title: "Task 18" },
{ id: "19", title: "Task 19" }
],
columnIds: ["todo"],
columns: {
todo: {
id: "todo",
title: "To do",
taskIds: [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19"
]
},
done: {
id: "done",
title: "Done",
taskIds: []
}
}
};
const COLUMN_ID_DONE = "done";
export const MultiTableDrag = () => {
const [entities, setEntities] = useState(entitiesMock);
const [selectedTaskIds, setSelectedTaskIds] = useState([]);
const [draggingTaskId, setDraggingTaskId] = useState(null);
const tableColumns = [
{
title: "ID",
dataIndex: "id"
},
{
title: "Title",
dataIndex: "title"
}
];
/**
* Droppable table body
*/
const DroppableTableBody = ({ columnId, tasks, ...props }) => {
return (
<Droppable droppableId={columnId}>
{(provided, snapshot) => (
<tbody
ref={provided.innerRef}
{...props}
{...provided.droppableProps}
className={`${props.className} ${
snapshot.isDraggingOver && columnId === COLUMN_ID_DONE
? "is-dragging-over"
: ""
}`}
>
{props.children}
{provided.placeholder}
</tbody>
)}
</Droppable>
);
};
/**
* Draggable table row
*/
const DraggableTableRow = ({ index, record, columnId, tasks, ...props }) => {
if (!tasks.length) {
return (
<tr className="ant-table-placeholder row-item" {...props}>
<td colSpan={tableColumns.length} className="ant-table-cell">
<div className="ant-empty ant-empty-normal">
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</div>
</td>
</tr>
);
}
const isSelected = selectedTaskIds.some(
(selectedTaskId) => selectedTaskId === record.id
);
const isGhosting =
isSelected && Boolean(draggingTaskId) && draggingTaskId !== record.id;
return (
<Draggable
key={props["data-row-key"]}
draggableId={props["data-row-key"].toString()}
index={index}
>
{(provided, snapshot) => {
return (
<tr
ref={provided.innerRef}
{...props}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={`row-item ${isSelected ? "row-selected" : ""} ${
isGhosting ? "row-ghosting" : ""
} ${snapshot.isDragging ? "row-dragging" : ""}`}
>
{props.children}
</tr>
);
}}
</Draggable>
);
};
/**
* Get tasks
*/
const getTasks = (entities, id) => {
return entities.columns[id].taskIds.map((taskId) =>
entities.tasks.find((item) => item.id === taskId)
);
};
/**
* On before capture
*/
const onBeforeCapture = (start) => {
const draggableId = start.draggableId;
const selected = selectedTaskIds.find((taskId) => taskId === draggableId);
// if dragging an item that is not selected - unselect all items
if (!selected) {
setSelectedTaskIds([]);
}
setDraggingTaskId(draggableId);
};
/**
* On drag end
*/
const onDragEnd = (result) => {
const destination = result.destination;
const source = result.source;
// nothing to do
if (!destination || result.reason === "CANCEL") {
setDraggingTaskId(null);
return;
}
const processed = mutliDragAwareReorder({
entities,
selectedTaskIds,
source,
destination
});
setEntities(processed.entities);
setDraggingTaskId(null);
};
return (
<>
<Card
className={`c-multi-drag-table ${draggingTaskId ? "is-dragging" : ""}`}
>
<div>
selectedTaskIds: {JSON.stringify(selectedTaskIds)}
<br />
draggingTaskId: {JSON.stringify(draggingTaskId)}
</div>
<br />
<DragDropContext
onBeforeCapture={onBeforeCapture}
onDragEnd={onDragEnd}
>
<Row gutter={40}>
{entities.columnIds.map((id) => (
<Col key={id} xs={12}>
<div className="inner-col">
<Row justify="space-between" align="middle">
<h2>{id}</h2>
<span>
{draggingTaskId && selectedTaskIds.length > 0
? selectedTaskIds.length +
" record(s) are being dragged"
: draggingTaskId && selectedTaskIds.length <= 0
? "1 record(s) are being dragged"
: ""}
</span>
</Row>
<Table
dataSource={getTasks(entities, id)}
columns={tableColumns}
rowKey="id"
components={{
body: {
// Custom tbody
wrapper: (val) =>
DroppableTableBody({
columnId: entities.columns[id].id,
tasks: getTasks(entities, id),
...val
}),
// Custom td
row: (val) =>
DraggableTableRow({
tasks: getTasks(entities, id),
...val
})
}
}}
// Set props on per row (td)
onRow={(record, index) => ({
index,
record
})}
/>
</div>
</Col>
))}
</Row>
<br />
</DragDropContext>
</Card>
</>
);
};
I am trying to integrate React-Beautiful-DND and Ant Design table, but I am facing an issue with rows as I drag them. Their style is changing and the whole table jumps. Anyone tried this before? How do I keep the style of dragged row as it was when it was not dragged?
Any ideas will be much appreciated.
Here is a link to full sandbox.
You can see that if you drag any row, the table will jump.
An here is a full code from the link:
import React, { useState } from "react";
import { Table, Row, Col, Card, Empty } from "antd";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import { mutliDragAwareReorder } from "./utils";
import "./style.css";
const entitiesMock = {
tasks: [
{ id: "0", title: "Very long task title" },
{ id: "1", title: "Task 1" },
{ id: "2", title: "Task 2" },
{ id: "3", title: "Task 3" },
{ id: "4", title: "Task 4" },
{ id: "5", title: "Task 5" },
{ id: "6", title: "Task 6" },
{ id: "7", title: "Task 7" },
{ id: "8", title: "Task 8" },
{ id: "9", title: "Task 9" },
{ id: "10", title: "Task 10" },
{ id: "11", title: "Task 11" },
{ id: "12", title: "Task 12" },
{ id: "13", title: "Task 13" },
{ id: "14", title: "Task 14" },
{ id: "15", title: "Task 15" },
{ id: "16", title: "Task 16" },
{ id: "17", title: "Task 17" },
{ id: "18", title: "Task 18" },
{ id: "19", title: "Task 19" }
],
columnIds: ["todo"],
columns: {
todo: {
id: "todo",
title: "To do",
taskIds: [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19"
]
},
done: {
id: "done",
title: "Done",
taskIds: []
}
}
};
const COLUMN_ID_DONE = "done";
export const MultiTableDrag = () => {
const [entities, setEntities] = useState(entitiesMock);
const [selectedTaskIds, setSelectedTaskIds] = useState([]);
const [draggingTaskId, setDraggingTaskId] = useState(null);
const tableColumns = [
{
title: "ID",
dataIndex: "id"
},
{
title: "Title",
dataIndex: "title"
}
];
/**
* Droppable table body
*/
const DroppableTableBody = ({ columnId, tasks, ...props }) => {
return (
<Droppable droppableId={columnId}>
{(provided, snapshot) => (
<tbody
ref={provided.innerRef}
{...props}
{...provided.droppableProps}
className={`${props.className} ${
snapshot.isDraggingOver && columnId === COLUMN_ID_DONE
? "is-dragging-over"
: ""
}`}
>
{props.children}
{provided.placeholder}
</tbody>
)}
</Droppable>
);
};
/**
* Draggable table row
*/
const DraggableTableRow = ({ index, record, columnId, tasks, ...props }) => {
if (!tasks.length) {
return (
<tr className="ant-table-placeholder row-item" {...props}>
<td colSpan={tableColumns.length} className="ant-table-cell">
<div className="ant-empty ant-empty-normal">
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</div>
</td>
</tr>
);
}
const isSelected = selectedTaskIds.some(
(selectedTaskId) => selectedTaskId === record.id
);
const isGhosting =
isSelected && Boolean(draggingTaskId) && draggingTaskId !== record.id;
return (
<Draggable
key={props["data-row-key"]}
draggableId={props["data-row-key"].toString()}
index={index}
>
{(provided, snapshot) => {
return (
<tr
ref={provided.innerRef}
{...props}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={`row-item ${isSelected ? "row-selected" : ""} ${
isGhosting ? "row-ghosting" : ""
} ${snapshot.isDragging ? "row-dragging" : ""}`}
>
{props.children}
</tr>
);
}}
</Draggable>
);
};
/**
* Get tasks
*/
const getTasks = (entities, id) => {
return entities.columns[id].taskIds.map((taskId) =>
entities.tasks.find((item) => item.id === taskId)
);
};
/**
* On before capture
*/
const onBeforeCapture = (start) => {
const draggableId = start.draggableId;
const selected = selectedTaskIds.find((taskId) => taskId === draggableId);
// if dragging an item that is not selected - unselect all items
if (!selected) {
setSelectedTaskIds([]);
}
setDraggingTaskId(draggableId);
};
/**
* On drag end
*/
const onDragEnd = (result) => {
const destination = result.destination;
const source = result.source;
// nothing to do
if (!destination || result.reason === "CANCEL") {
setDraggingTaskId(null);
return;
}
const processed = mutliDragAwareReorder({
entities,
selectedTaskIds,
source,
destination
});
setEntities(processed.entities);
setDraggingTaskId(null);
};
return (
<>
<Card
className={`c-multi-drag-table ${draggingTaskId ? "is-dragging" : ""}`}
>
<div>
selectedTaskIds: {JSON.stringify(selectedTaskIds)}
<br />
draggingTaskId: {JSON.stringify(draggingTaskId)}
</div>
<br />
<DragDropContext
onBeforeCapture={onBeforeCapture}
onDragEnd={onDragEnd}
>
<Row gutter={40}>
{entities.columnIds.map((id) => (
<Col key={id} xs={12}>
<div className="inner-col">
<Row justify="space-between" align="middle">
<h2>{id}</h2>
<span>
{draggingTaskId && selectedTaskIds.length > 0
? selectedTaskIds.length +
" record(s) are being dragged"
: draggingTaskId && selectedTaskIds.length <= 0
? "1 record(s) are being dragged"
: ""}
</span>
</Row>
<Table
dataSource={getTasks(entities, id)}
columns={tableColumns}
rowKey="id"
components={{
body: {
// Custom tbody
wrapper: (val) =>
DroppableTableBody({
columnId: entities.columns[id].id,
tasks: getTasks(entities, id),
...val
}),
// Custom td
row: (val) =>
DraggableTableRow({
tasks: getTasks(entities, id),
...val
})
}
}}
// Set props on per row (td)
onRow={(record, index) => ({
index,
record
})}
/>
</div>
</Col>
))}
</Row>
<br />
</DragDropContext>
</Card>
</>
);
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论