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.
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 </StyledTableCell>
<StyledTableCell align="right">Defaults </StyledTableCell>
<StyledTableCell align="right">Type </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.
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>