【问题标题】:Use material-ui table with react-beautiful-dnd使用带有 react-beautiful-dnd 的 material-ui 表
【发布时间】:2018-08-14 10:28:24
【问题描述】:

我希望将 material-ui 与 react-beautiful-dnd 结合使用,以制作可排序的表格。但是,使用 material-ui 的表格组件会导致麻烦,因为 TableBody 不会接受 innerRef 并且 TableRow 不会接受 innerRef 和 isDragging。请参阅下面的代码:

<DragDropContext onDragEnd={this.onDragEnd}>
  <Fragment>
    <Table className={classes.table}>
      <TableHead>
        <TableRow>
          <TableCell />
          <TableCell>Name</TableCell>
          <TableCell numeric>Number</TableCell>
          <TableCell>Time</TableCell>
        </TableRow>
      </TableHead>
      <Droppable droppableId="table">
        {(droppableProvided) => (
          <TableBody
            innerRef={(ref) => {
              this.tableRef = ref;
              droppableProvided.innerRef(ref);
            }}
            {...droppableProvided.droppableProps}
          >
            {this.state.users.map((user, index) => (
              <Draggable
                draggableId={user.id}
                index={index}
                key={user.id}
              >
                {(
                  provided,
                  snapshot,
                ) => (
                  <TableRow
                    innerRef={provided.innerRef}
                    isDragging={snapshot.isDragging}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    <TableCell><DragIndicatorIcon /></TableCell>
                    <TableCell>{user.name}</TableCell>
                    <TableCell numeric>{user.number}</TableCell>
                    <TableCell>10</TableCell>
                  </TableRow>
                )}
              </Draggable>
            ))}
          </TableBody>
        )}
      </Droppable>
    </Table>
  </Fragment>
</DragDropContext>

如何让 material-ui 与这些属性一起使用?

【问题讨论】:

  • 你让它工作了吗?可以分享一下代码吗?
  • 我们最终转到了另一个不存在此问题的库 (react-drag-listview)。
  • @Yannick :您可以为stackoverflow.com/questions/63738982/… 提供的任何输入。我想做同样的事情,但在两张桌子之间。

标签: material-ui


【解决方案1】:

我遇到了同样的问题。您要做的就是将 Draggable/Droppable 部分移动到组件中,并通过组件属性将其传入。

例如,我希望能够对表头中的列重新排序。 Row 是我的可放置区域,Cell 是 Draggable。

public render() {
    return (
        <TableHead component="div">
            <TableRow component={DroppableComponent(this.onDragEnd)}>{headerCells}</TableRow>
        </TableHead>
    );
}

const DroppableComponent = (
    onDragEnd: (result: DropResult, provided: ResponderProvided) => void
) => (props: any) => {
    return (
        <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId={'1'} direction="horizontal">
                {(provided) => {
                    return (
                        <div ref={provided.innerRef} {...provided.droppableProps} {...props}>
                            {props.children}
                            {provided.placeholder}
                        </div>
                    );
                }}
            </Droppable>
        </DragDropContext>
    );
};

请注意,我将 Droppable Component 设为返回函数的函数。这样我就可以从我的主要组件中传入 onDragEnd 方法。我尝试将我的 DroppableComponent 作为 JSX 放在组件属性中,但我遇到了一个错误,所以这就是我最终的结果。

对于 Draggable 部分,我有以下内容:

<TableCell
    component={DraggableComponent(column.id, index)}
    key={column.id}
>
    ...
</TableCell>

const DraggableComponent = (id: string, index: number) => (props: any) => {
    return (
        <Draggable draggableId={id} index={index}>
            {(provided) => (
                <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    {...props}
                >
                    {props.children}
                </div>
            )}
        </Draggable>
    );
};

希望这会有所帮助!

【讨论】:

  • 你有 github repo 吗?
  • @Bryant:我们可以在两张桌子之间做同样的事情吗?即从左表拖放右表中的行?
  • @ShreyaBhatnagar 看起来像 react-beautiful-dnd 支持在两个容器/表格之间拖动,就像你问的那样。虽然我没有尝试在这种情况下使用我上面的解决方案,但原则上它应该可以工作。我也不再积极使用这个库了。
【解决方案2】:

我在处理类似任务时遇到了这个问题。关于 OP 的问题,TableRowTableBody 都支持转发到根元素的ref 道具(与innerRef)。

请参阅常见问题解答:

TableRowTableBody 的文档中都提到了这一点:

因此,您不一定需要根据@Bryant 和@funql.org 的答案将可拖动/可放置部分移动到它们自己的组件中。

您也不一定需要将isDragging 传递给您的TableRow(尽管如果您创建了一个接受此道具的自定义包装器组件,则可以)。如果您的用例在拖动时设置该行的样式,您可以将 classNamestyle 属性添加到您的 TableRow 并在 isDraggingtrue 时应用条件样式。

这是一个使用 react-beautiful-dnd 的 Material UI 表的工作示例:

顺便说一句,我将它创建为issue report 的一部分,因为我不确定为什么在拖动给定表格行时会出现 1 个像素的跳跃(表格单元格底部边框的厚度),但这是另一个问题!该实现足够可靠,足以支持可接受 1px 视觉小故障的许多情况。

【讨论】:

  • 您的工作示例有一些缺陷,这也发生在我身上。拖动行时,它会“缩小”其宽度,导致整个内容难以阅读。我仍在努力寻找解决此问题的方法。
  • 似乎自动注入了很多特定于元素的样式,导致可拖动对象缩小。由于特定于元素的样式会覆盖任何类样式(除非您管理丑陋的 !important 属性以通过),因此当 isDragging 为 true 时提供一些类将无法解决此问题。
  • 嗨@RuiMiguelPinheiro 我没有费心去实现这个细节,因为我最初为错误报告创建了那个代码框。但是,如果您查看MaterialTable.tsx 中的代码,我实际上对这种收缩行为发表了评论并提出了解决方案:)。我有一个项目,我在其中实现了一个 DraggableTableCell,它使用了一个使用 ResizeObserver API 的 useMeasure() 钩子。当 isDragging 属性为真时,它使用从钩子获得的“缓存”宽度 + 高度以内联样式“锁定”单元格的宽度 + 高度。这样就解决了问题。
  • 对于任何需要这个的人,@firxworx 为宽度收缩概述的解决方案在这里有一个足够接近的实现:github.com/pschlan/cron-job.org/blob/… 奇怪的是它在我更改 if (isDragging) --> if (!isDragging) 后工作
【解决方案3】:

我使用@Bryant 的解决方案创建了一个 github 示例存储库。 https://github.com/hmarggraff/react-material-ui-table-row-drag-and-drop

它展示了如何将 Bryants 解决方案与 react-material-ui 结合起来。它还显示行与列 dnd 和 dnd 期间的视觉反馈。这是一个完全可重复使用的解决方案。

【讨论】:

  • 与 Bryant 的答案相比,此答案提供的额外好处或见解是什么?我的意思是除了对你的好处之外,它可能会吸引用户到你的 github,尽管技术不是你的。如果您提供更多,请在此处说明。否则,请考虑这篇文章是否会给您的意图留下不利的印象。更多的解释可能会更好地说明它。此外,这可能会被误认为是仅链接的答案,因此可能会被删除。
  • 它回答了Kimaya的请求。并且它提供了一个完整的重复使用解决方案。不仅仅是代码片段。它展示了如何将 Bryants 解决方案与 react-material-ui 结合起来。它还显示行与列 dnd 和 dnd 期间的视觉反馈。除了增加评论数量之外,您的评论有什么好处?
  • 看,这是额外的好处。然而,现在它是一个仅限链接的答案,因为它只说明链接提供的内容,而不是如何完成的。您可以通过直接在答案中描述实现额外收益的核心方法来改变这一点。 (顺便说一句,反对票不是我的。)
  • 对了,我看到有人要了一个github。但是人们希望在 StackOverflow 上找到的内容与 StackOverflow 旨在提供或设计允许的内容是不同的。
  • @funql.org 我们可以在两张桌子之间做同样的事情吗?即从左表拖放右表中的行?
猜你喜欢
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
  • 2019-04-24
  • 2019-03-19
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
相关资源
最近更新 更多