Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use material-ui table with react-beautiful-dnd

Tags:

material-ui

I'm looking to use material-ui in combination with react-beautiful-dnd in order to make a sortable table. However, using material-ui's table components causes trouble as TableBody won't accept innerRef and TableRow won't accept innerRef and isDragging. See my code below:

<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>

How can I get material-ui to be usable with these attributes?

like image 409
Yannick Avatar asked Aug 14 '18 10:08

Yannick


2 Answers

I have created a github example repo using @Bryant's solution. https://github.com/hmarggraff/react-material-ui-table-row-drag-and-drop

It shows how to combine Bryants solution with react-material-ui. It also shows row vs colums dnd and visual feedback during dnd. It is a complete reusable solution.

like image 61
funql.org Avatar answered Oct 19 '22 01:10

funql.org


I came across this while working on a similar task. Re the OP's question, TableRow and TableBody both support a ref prop (vs. innerRef) that forwards to the root element.

Refer to the FAQ:

  • https://material-ui.com/getting-started/faq/#how-can-i-access-the-dom-element

This is mentioned in the docs for both TableRow and TableBody:

  • https://material-ui.com/api/table-row/
  • https://material-ui.com/api/table-body/

Therefore you do not necessarily need to move the Draggable/Droppable parts into their own components per the answers from @Bryant and @funql.org.

You also don't necessarily need to pass isDragging to your TableRow (though you could if you created a custom wrapper component that accepts this prop). If your use-case is styling the row when dragged, you can add a className or style prop to your TableRow and apply conditional styling when isDragging is true.

Here's a working example of a Material UI table that features sortable rows with react-beautiful-dnd:

  • https://codesandbox.io/s/react-material-ui-and-react-beautiful-dnd-uofv4

Incidentally I created it as part of an issue report because I'm not sure why there is a 1 pixel jump (the thickness of the border-bottom on table cells) when a given table row is dragged, but that's another issue! The implementation is solid enough to support the many cases where a minor 1px visual glitch is acceptable.

like image 24
firxworx Avatar answered Oct 19 '22 02:10

firxworx