Material-ui: [Table] Nested table changes design

Created on 24 Sep 2018  路  3Comments  路  Source: mui-org/material-ui

I want to create a nested table in React relying on Material UI. Basically, I have something like this:

    import React from "react";
    import ReactDOM from "react-dom";

    import IconButton from "@material-ui/core/IconButton";
    import Paper from "@material-ui/core/Paper";
    import Table from "@material-ui/core/Table";
    import TableBody from "@material-ui/core/TableBody";
    import TableCell from "@material-ui/core/TableCell";
    import TableFooter from "@material-ui/core/TableFooter";
    import TableHead from "@material-ui/core/TableHead";
    import TableRow from "@material-ui/core/TableRow";
    import SvgMore from "@material-ui/icons/ExpandMore";

    class App extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          expand: false
        };

        this.handleExpand = this.handleExpand.bind(this);
      }

      handleExpand = () => {
        this.setState({
          expand: !this.state.expand
        });
      };

      render() {
        return (
          <div className="App">
            <Paper>
              <Table>
                <TableHead>
                  <TableRow>
                    <TableCell>One</TableCell>
                    <TableCell>Two</TableCell>
                    <TableCell>Three</TableCell>
                    <TableCell>Expand</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  <React.Fragment>
                    <TableRow>
                      <TableCell>1</TableCell>
                      <TableCell>2</TableCell>
                      <TableCell>3</TableCell>
                      <TableCell>
                        <IconButton onClick={this.handleExpand}>
                          <SvgMore />
                        </IconButton>
                      </TableCell>
                    </TableRow>
                    {this.state.expand ? (
                      <Table>
                        <TableHead>
                          <TableRow>
                            <TableCell>One</TableCell>
                            <TableCell>Two</TableCell>
                            <TableCell>Three</TableCell>
                          </TableRow>
                        </TableHead>
                        <TableBody>
                          <TableRow>
                            <TableCell>1</TableCell>
                            <TableCell>2</TableCell>
                            <TableCell>3</TableCell>
                          </TableRow>
                        </TableBody>
                      </Table>
                    ) : (
                      ""
                    )}
                  </React.Fragment>
                </TableBody>
              </Table>
            </Paper>
          </div>
        );
      }
    }

    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);

You can run it from here: https://codesandbox.io/s/wnk9132n1w

It works to some extend, but the problem is that when you try to expand the first row, so that it displays the other table underneath, it displays the other table fully under the first column of the parent table, and shifts the other columns to the right, hence, increasing the size of the parent table. I kind of want it to seamlessly be displayed underneath the row, without making any drastic changes to the size or margin or padding of the original parent table. Any ideas how to achieve this with React and Material UI?

support

Most helpful comment

@etairi You would face the same issue by using a native HTML5 table. I'm sorry but the Material-UI tracker isn't a help forum.
However, because we want to help people getting started wit Material-UI I will answer your question thi time. Basically, you can use the table colspan feature:

import React from "react";
import ReactDOM from "react-dom";

import IconButton from "@material-ui/core/IconButton";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableFooter from "@material-ui/core/TableFooter";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import SvgMore from "@material-ui/icons/ExpandMore";

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      expand: false
    };

    this.handleExpand = this.handleExpand.bind(this);
  }

  handleExpand = () => {
    this.setState({
      expand: !this.state.expand
    });
  };

  render() {
    return (
      <div className="App">
        <Paper>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell>One</TableCell>
                <TableCell>Two</TableCell>
                <TableCell>Three</TableCell>
                <TableCell>Expand</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              <TableRow>
                <TableCell>1</TableCell>
                <TableCell>2</TableCell>
                <TableCell>3</TableCell>
                <TableCell>
                  <IconButton onClick={this.handleExpand}>
                    <SvgMore />
                  </IconButton>
                </TableCell>
              </TableRow>
              {this.state.expand ? (
                <TableRow>
                  <TableCell colSpan="3">
                    <Table>
                      <TableHead>
                        <TableRow>
                          <TableCell>One</TableCell>
                          <TableCell>Two</TableCell>
                          <TableCell>Three</TableCell>
                        </TableRow>
                      </TableHead>
                      <TableBody>
                        <TableRow>
                          <TableCell>1</TableCell>
                          <TableCell>2</TableCell>
                          <TableCell>3</TableCell>
                        </TableRow>
                      </TableBody>
                    </Table>
                  </TableCell>
                </TableRow>
              ) : null}
            </TableBody>
          </Table>
        </Paper>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/s/l9k64nny4z

All 3 comments

馃憢 Thanks for using Material-UI!

We use the issue tracker exclusively for bug reports and feature requests, however,
this issue appears to be a support request or question. Please ask on StackOverflow where the
community will do their best to help. There is a "material-ui" tag that you can use to tag your
question.

If you would like to link from here to your question on SO, it will help others find it.
If your issues is confirmed as a bug, you are welcome to reopen the issue using the issue template.

@etairi You would face the same issue by using a native HTML5 table. I'm sorry but the Material-UI tracker isn't a help forum.
However, because we want to help people getting started wit Material-UI I will answer your question thi time. Basically, you can use the table colspan feature:

import React from "react";
import ReactDOM from "react-dom";

import IconButton from "@material-ui/core/IconButton";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableFooter from "@material-ui/core/TableFooter";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import SvgMore from "@material-ui/icons/ExpandMore";

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      expand: false
    };

    this.handleExpand = this.handleExpand.bind(this);
  }

  handleExpand = () => {
    this.setState({
      expand: !this.state.expand
    });
  };

  render() {
    return (
      <div className="App">
        <Paper>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell>One</TableCell>
                <TableCell>Two</TableCell>
                <TableCell>Three</TableCell>
                <TableCell>Expand</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              <TableRow>
                <TableCell>1</TableCell>
                <TableCell>2</TableCell>
                <TableCell>3</TableCell>
                <TableCell>
                  <IconButton onClick={this.handleExpand}>
                    <SvgMore />
                  </IconButton>
                </TableCell>
              </TableRow>
              {this.state.expand ? (
                <TableRow>
                  <TableCell colSpan="3">
                    <Table>
                      <TableHead>
                        <TableRow>
                          <TableCell>One</TableCell>
                          <TableCell>Two</TableCell>
                          <TableCell>Three</TableCell>
                        </TableRow>
                      </TableHead>
                      <TableBody>
                        <TableRow>
                          <TableCell>1</TableCell>
                          <TableCell>2</TableCell>
                          <TableCell>3</TableCell>
                        </TableRow>
                      </TableBody>
                    </Table>
                  </TableCell>
                </TableRow>
              ) : null}
            </TableBody>
          </Table>
        </Paper>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

https://codesandbox.io/s/l9k64nny4z

@oliviertassinari Thanks, this seems to work better.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aranw picture aranw  路  95Comments

illogikal picture illogikal  路  75Comments

kybarg picture kybarg  路  164Comments

nathanmarks picture nathanmarks  路  100Comments

gndplayground picture gndplayground  路  54Comments