How to create a table with multiple rows in one row (Material-UI)

Viewed 32

this is my api data:

    const data =[
      {"id":"1", "lo":{"code":101,"value":"right","pcode":10}, "kind":"a"},
      {"id":"2", "lo":{"code":101,"value":"right","pcode":10}, "kind":"b"},
      {"id":"3", "lo":{"code":101,"value":"right","pcode":10}, "kind":"c"},
      {"id":"4", "lo":{"code":102,"value":"left","pcode":10}, "kind":"d"},
      {"id":"5", "lo":{"code":102,"value":"left","pcode":10}, "kind":"e"},
      {"id":"6", "lo":{"code":103,"value":"center","pcode":10}, "kind":"f"},
      {"id":"7", "lo":{"code":103,"value":"center","pcode":10}, "kind":"g"},
      {"id":"8", "lo":{"code":103,"value":"center","pcode":10}, "kind":"h"},
      {"id":"9", "lo":{"code":104,"value":"bottom","pcode":10}, "kind":"i"},
    ];

I want to make it like this

enter image description here

I want to solve it using mui's tableCell and tableRow I had a similar question, so I looked it up, but it wasn't successful because of my lack of it. I'm not good at English, so I'm sorry that I'm not good at writing a question because it's my first time asking a question.

1 Answers

You need to group and map your data before passing it to the table in order to handle rowSpan like this:

import React, { Fragment } from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";

const data = [
  { id: "1", lo: { code: 101, value: "right", pcode: 10 }, kind: "a" },
  { id: "2", lo: { code: 101, value: "right", pcode: 10 }, kind: "b" },
  { id: "3", lo: { code: 101, value: "right", pcode: 10 }, kind: "c" },
  { id: "4", lo: { code: 102, value: "left", pcode: 10 }, kind: "d" },
  { id: "5", lo: { code: 102, value: "left", pcode: 10 }, kind: "e" },
  { id: "6", lo: { code: 103, value: "center", pcode: 10 }, kind: "f" },
  { id: "7", lo: { code: 103, value: "center", pcode: 10 }, kind: "g" },
  { id: "8", lo: { code: 103, value: "center", pcode: 10 }, kind: "h" },
  { id: "9", lo: { code: 104, value: "bottom", pcode: 10 }, kind: "i" }
];

const valueData = data.map((d) => {
  return d.lo.value;
});

let uniqueValueData = [...new Set(valueData)];

const mappedData = uniqueValueData.map((md) => {
  const result = { lo: md, subItems: [] };
  data.forEach((d) => {
    if (d.lo.value === md) {
      result.subItems.push({ id: d.id, kind: d.kind });
    }
  });
  return result;
});

export default function SpanningTable() {
  return (
    <Paper>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>lo</TableCell>
            <TableCell>id</TableCell>
            <TableCell>kind</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {mappedData.map((item) => (
            <Fragment>
              <TableRow>
                <TableCell rowSpan={item.subItems.length + 1}>
                  {item.lo}
                </TableCell>
              </TableRow>
              {item.subItems.map((detail) => (
                <TableRow>
                  <TableCell>{detail.id}</TableCell>
                  <TableCell>{detail.kind}</TableCell>
                </TableRow>
              ))}
            </Fragment>
          ))}
        </TableBody>
      </Table>
    </Paper>
  );
}

You can take a look at this sandbox for a live working example of this solution.

Related