1

I am using one of materialUI's built-in components to display data on one of my sites. Currently, the code that was implemented is very closely based off of the examples on the MaterialUI API site. With that said, I have made a few adjustments for my own personal use case. This is how each of the columns that I need are labeled (5 total). I've also included my code below.

CustomTable

import React from 'react';
import {
  withStyles,
  Theme,
  createStyles,
  makeStyles,
} from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

const StyledTableCell = withStyles((theme: Theme) =>
  createStyles({
    head: {
      backgroundColor: '#533cf8',
      color: theme.palette.common.white,
      fontSize: 11,
    },
    body: {
      fontSize: 10,
    },
  }),
)(TableCell);

const StyledTableRow = withStyles((theme: Theme) =>
  createStyles({
    root: {
      '&:nth-of-type(odd)': {
        backgroundColor: theme.palette.action.hover,
      },
    },
  }),
)(TableRow);

function createData(
  parameters: string,
  required: string,
  description: string,
  defaults: string,
  type: string,
) {
  return { parameters, required, description, defaults, type };
}

const rows = [
  createData('id', 'yes', 'id to update', 'n/a', 'string'),
  // eslint-disable-next-line prettier/prettier
  createData('start', 'no', 'datetime in YYYY-MM-DD HH:mm:ss format that specifies the start', 'n/a', 'string',),
  // eslint-disable-next-line prettier/prettier
  createData('end', 'no', 'datetime string in YYYY-MM-DD HH:mm:ss format that specifies the end', 'n/a', 'string',),
  // eslint-disable-next-line prettier/prettier
  createData('provider', 'no', 'subdomain of the provider this affects', 'n/a', 'string',),
  createData('resources', 'no', 'list of ids for resources', 'n/a', 'string[]'),
];

const useStyles = makeStyles({
  main: {
    maxWidth: '90%',
    marginRight: 'auto',
    marginBottom: '75px',
    marginLeft: '25px',
    borderRadius: '8px',
  },
});

export default function CustomTable(): JSX.Element {
  const classes = useStyles();

  return (
    <TableContainer
      component={Paper}
      className={classes.main}
      elevation={0}
      style={{
        borderRight: '0.3px solid lightgray',
        borderLeft: '0.3px solid lightgray',
      }}
    >
      <Table aria-label="customized table">
        <TableHead>
          <TableRow>
            <StyledTableCell>Parameters</StyledTableCell>
            <StyledTableCell align="right">Required</StyledTableCell>
            <StyledTableCell align="right">Description&nbsp;</StyledTableCell>
            <StyledTableCell align="right">Defaults&nbsp;</StyledTableCell>
            <StyledTableCell align="right">Type&nbsp;</StyledTableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {rows.map((row) => (
            <StyledTableRow key={row.parameters}>
              <StyledTableCell component="th" scope="row">
                {row.parameters}
              </StyledTableCell>
              <StyledTableCell align="right">{row.required}</StyledTableCell>
              <StyledTableCell align="right">{row.description}</StyledTableCell>
              <StyledTableCell align="right">{row.defaults}</StyledTableCell>
              <StyledTableCell align="right">{row.type}</StyledTableCell>
            </StyledTableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

For my project, I am going to be using this table many, many times. The column headings won't be changing, but the number of rows/parameters will definitely be changing. For example, there might be a table with only 2 rows, while another could have up to 8.

In my current code, the table is being populated using the 'const rows' variable, but since I am using this component throughout my site, I want to pass something similar using props/variables, instead of having to create a new component each time I want to fill a table with data. I am relatively new to ReactJS, so any help is much appreciated. Thank you.

4
  • It sounds like you have the right idea. Are you just not familiar with how to pass props? Commented Jun 14, 2021 at 17:13
  • Not quite, would I just want to create a prop for the 'rows' variable? Commented Jun 14, 2021 at 17:32
  • Yes. Then the parent component can pass it the rows. Here's a simplified example codesandbox.io/s/charming-williamson-zb631?file=/src/App.tsx Commented Jun 14, 2021 at 17:41
  • Thanks, that example is helpful. If you want to comment that solution, I'll try to upvote it. Commented Jun 14, 2021 at 17:49

1 Answer 1

1

You have the right idea about passing props to your CustomTable component to be able to change the data that gets rendered. Then, the parent component can pass the rows through the CustomTable component's props.

Here's a simplified example

interface Row {
  id: string;
  data: string;
}

export interface TableProps {
  rows: Row[];
}

// Not really a table
export function Table({ rows }: TableProps) {
  return (
    <>
      {rows.map((row) => (
        <div key={row.id}>{row.data}</div>
      ))}
    </>
  );
}

const rows: Row[] = [
  { id: "0", data: "foo" },
  { id: "1", data: "bar" },
  { id: "2", data: "baz" }
];

export default function App() {
  return (
    <div className="App">
      <Table rows={rows} />
    </div>
  );
}

And an interactive one:

const { useState, Fragment } = React;

const Table = ({ rows }) => {
  return (
    <Fragment>
      {rows.map((row) => (
        <div key={row.id}>{row.data}</div>
      ))}
    </Fragment>
  );
}


const App = () => {
  const [rows, setRows] = useState([]);
  const [value, setValue] = useState('');
  
  const handleChange = (e) => {
    setValue(e.target.value);
  }
  
  const handleSubmit = (e) => {
    e.preventDefault();
    setValue('');
    setRows((state) => [...state, {id: uuidv4(), data: value}]);
  };
  
  return (
    <div>
      <Table rows={rows} />
      <form onSubmit={handleSubmit}>
        <label>
          Data
          <input value={value} onChange={handleChange} />
        </label>
        <button type="submit">Add row</button>
      </form>
    </div>
  );
}

ReactDOM.render(<App />, document.body);
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/uuid@latest/dist/umd/uuidv4.min.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.