Material UI TableCell can't force a string to display in a new line like list items

Viewed 5321

I'm working with a "Books" table in Material UI. It has 3 columns: "Book Number", "Title", and "Chapters". I would like each chapter to be displayed in individual lines like list items, like so:

Chapter 1

Chapter 2

Chapter 3

and not

Chapter 1 Chapter 2 Chapter 3

I tried different approaches such as adding "\n", storing it in variable, and/or enclosing it in a template literal, like so:

const row2 = "Chapter 1\nChapter 2";
const row4 = `Chapter 1\nChapter 2\nChapter 3`;

const rows = [
  createData("1", "Book 1", "Not Applicable"),
  createData("2", "Book 2", row2),
  createData("3", "Book 3", "Chapter 1\nChapter 2"),
  createData("4", "Book 4", row4)
];

Here's the complete code.

2 Answers

I would create a Chapters component that would accept a value prop — this value would be then converted to array using split("\n") and will be used to display each chapter as list item.

function Chapters({ value }) {
  const chapters = value.split("\n");

  return (
    <List>
      {chapters.map((chapter, i) => (
        <ListItem key={i}>{chapter}</ListItem>
      ))}
    </List>
  );
}

Then on my columns.map, I would check for column.label === "Chapters"; if it is true, I would reassign the value calling my Chapters component.

...
{
  rows.map((row) => {
    return (
      <TableRow hover role="checkbox" key={row.annex}>
        {columns.map((column) => {
          let value = row[column.id];

          if (column.label === "Chapters") {
            value = <Chapters value={value} />;
          }

          return <TableCell key={column.id}>{value}</TableCell>;
        })}
      </TableRow>
    );
  });
}

Edit cool-cloud-gjz9m

Converting the array into a list is a good option, but you will also need to add a little css to avoid adding a ton of padding to your cell.

I needed this recently on a couple of tables, the cell formats were unreliable to detect from the API return, so I added an extra key in the column definitions then ran the cell value through that using the column format in a switch statement.

The array case then just looks like:

val = (
    <List className="table-cell-list">
      {val.map((item, i) => (
        <ListItem className="table-cell-list" key={i}>{item}</ListItem>
      ))}
    </List>
  );

And the css:

.table-cell-list {
    padding: 0 !important;
}

The roles column on this table is an array field, multiple values split out on new lines without excess spacing:

enter image description here

Related