How to group table in reactjs? - reactjs

I am using the Table control from material UI to display the data , but right now I have the requirement to show the group data,with expand and collapsed data.Is there any package present to achieve this goal?Please assist me.
import { TableRowProps, Table, TableBody, TableFooter, PagiFooter, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
<Table>
<TableHeader {...headerProps}>
{this.renderHeaders()}
</TableHeader>
<TableBody displayRowCheckbox={false}
deselectOnClickaway={false}>
{this.renderRows()}
</TableBody>
</Table>

The Table component doesn't currently support expansion, but you can hack around that using the expandable card component, just make sure you adjust the vertical alignment of the row.
Here's a code snippet:
<TableBody displayRowCheckbox={false}>
{this.props.user.leads.map((lead, i) => (
<TableRow key={i}>
<TableRowColumn>
<Card style={{boxShadow: 'none'}}>
<CardHeader
title={lead.brand}
style={{paddingLeft: 0, fontWeight: 600}}
actAsExpander={true}
/>
<CardText expandable={true}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
</CardText>
</Card>
</TableRowColumn>
<TableRowColumn style={{verticalAlign: 'top', height: 'auto', paddingTop: '1.4em'}}>{lead.budget}</TableRowColumn>
<TableRowColumn style={{verticalAlign: 'top', height: 'auto', paddingTop: '1.4em'}}>{lead.eventName ? 'Event' : 'Content'}</TableRowColumn>
<TableRowColumn style={{verticalAlign: 'top', height: 'auto', paddingTop: '1.4em'}}>{lead.firstName + ' ' + lead.lastName}</TableRowColumn>
<TableRowColumn style={{verticalAlign: 'top', height: 'auto', paddingTop: '1.4em'}}>Archive | Start Campaign</TableRowColumn>
</TableRow>
))}
</TableBody>

An approach for Material Ui , but can be used with same structure in other table formats:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } 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 TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import Paper from '#material-ui/core/Paper';
import Collapse from '#material-ui/core/Collapse';
import CardActions from '#material-ui/core/CardActions';
import IconButton from '#material-ui/core/IconButton';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
const styles = theme => ({
root: {
width: '100%',
marginTop: theme.spacing.unit * 3,
overflowX: 'auto',
},
table: {
minWidth: 700,
},
expand: {
transform: 'rotate(0deg)',
transition: theme.transitions.create('transform', {
duration: theme.transitions.duration.shortest,
}),
marginLeft: 'auto',
[theme.breakpoints.up('sm')]: {
marginRight: -8,
},
},
expandOpen: {
transform: 'rotate(180deg)',
},
});
let id = 0;
function createData(name, calories, fat, carbs, protein) {
id += 1;
return { id, name, calories, fat, carbs, protein };
}
const rows = [
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Gingerbread', 356, 16.0, 49, 3.9),
createData('Gingerbread', 356, 16.0, 49, 3.9)
];
class TableGroup extends React.Component {
constructor(props) {
super(props);
this.state = { expanded: {} };
}
handleExpandClick(key) {
let state = { ...this.state };
state.expanded[key] = !!!state.expanded[key];
this.setState(state);
}
render() {
const props = this.props;
const { groupProperty, rows, ...other } = props;
const groups = rows.reduce((acc, row) => {
acc[row[groupProperty]] = acc[row[groupProperty]] || [];
acc[row[groupProperty]].push(row);
return acc;
}, {});
const keys = Object.keys(groups);
return keys.map(key => (
<TableRow>
<TableCell colspan="5">
<CardActions disableActionSpacing>
<b>{key} ({groups[key].length})</b>
<IconButton
className={this.state.expanded[key] ? props.classes.expandOpen : props.classes.expand}
onClick={this.handleExpandClick.bind(this, key)}
aria-expanded={this.state.expanded[key]}
aria-label="Show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={this.state.expanded[key]} timeout="auto" unmountOnExit>
<Table {...other}>
<TableBody>
{groups[key].map(row => (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell numeric>{row.calories}</TableCell>
<TableCell numeric>{row.fat}</TableCell>
<TableCell numeric>{row.carbs}</TableCell>
<TableCell numeric>{row.protein}</TableCell>
</TableRow>
)
)}
</TableBody>
</Table>
</Collapse>
</TableCell>
</TableRow>
)
)
}
};
function SimpleTable(props) {
const { classes } = props;
return (
<Paper className={classes.root}>
<Table >
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell numeric>Calories</TableCell>
<TableCell numeric>Fat (g)</TableCell>
<TableCell numeric>Carbs (g)</TableCell>
<TableCell numeric>Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableGroup classes={classes} rows={rows} groupProperty="name" />
</TableBody>
</Table>
</Paper>
);
}
SimpleTable.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(SimpleTable);

function createData(name, calories, fat, carbs, protein) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Gingerbread', 356, 16.0, 49, 3.9),
];
const DataCard = ({ show }) => {
const classes = useStyles();
const [open, setOpen] = useState();
const handleExpandedClick = index => (e) => {
setOpen(index === open ? '' : index);
}
return (
<Only when={show}>
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row, index) => (
<>
<TableRow
key={index}
hover
style={{ cursor: 'pointer' }}
onClick={handleExpandedClick(index)}
>
<TableCell component="th" scope="row">{row.name}</TableCell>
<TableCell align="right">{row.calories}</TableCell>
<TableCell align="right">{row.fat}</TableCell>
<TableCell align="right">{row.carbs}</TableCell>
<TableCell align="right">{row.protein}</TableCell>
</TableRow>
<Collapse in={open === index} hidden={open !== index} component="tr" style={{ display: "block" }}>
<td>
<div>Expanded data.</div>
</td>
</Collapse>
</>
))}
</TableBody>
</Table>
</Paper>
</Only>
)
}
DataCard.propTypes = {
show: PropTypes.bool.isRequired
}
export default DataCard;

Thank you #bluehipy, I have managed rewrite the code with hooks
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { withStyles } 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 TableHead from "#material-ui/core/TableHead";
import TableRow from "#material-ui/core/TableRow";
import Paper from "#material-ui/core/Paper";
import Collapse from "#material-ui/core/Collapse";
import CardActions from "#material-ui/core/CardActions";
import IconButton from "#material-ui/core/IconButton";
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
import getOrdersBasedOnRouteQuery from "../graphql/queries/getOrdersBasedOnRouteQuery";
const styles = theme => ({
root: {
width: "100%",
marginTop: theme.spacing.unit * 3,
overflowX: "auto"
},
table: {
minWidth: 700
},
expand: {
transform: "rotate(0deg)",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest
}),
marginLeft: "auto",
[theme.breakpoints.up("sm")]: {
marginRight: -8
}
},
expandOpen: {
transform: "rotate(180deg)"
}
});
const grouped = values => {
let finalArray = [];
values.customers.filter(orders => {
return Array.prototype.push.apply(finalArray, orders);
});
return finalArray;
};
const TableGroup = ({ classes, routes, ...other }) => {
const [expanded, setExpanded] = useState({});
const handleExpandClick = value => {
setExpanded(expanded => {
return {
...expanded,
[value]: expanded[value] ? false : true
};
});
};
return routes.map((route, routeIndex) => {
return (
<TableRow>
<TableCell colspan="5">
<CardActions disableActionSpacing>
<b>
{route.name} - ({grouped(route).length}){" "}
</b>
<IconButton
className={
expanded[route.name] ? classes.expandOpen : classes.expand
}
onClick={() => handleExpandClick(route.name)}
aria-expanded={route.name}
aria-label="Show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded[route.name]} timeout="auto" unmountOnExit>
<Table {...other}>
<TableBody>
{grouped(route).map(row => {
return (
<TableRow key={row.id}>
<TableCell text>{row.reference}</TableCell>
<TableCell text>{row.customer.full_name}</TableCell>
<TableCell numeric>{row.total}</TableCell>
<TableCell>{row.status}</TableCell>
<TableCell>{row.created_at}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Collapse>
</TableCell>
</TableRow>
);
});
};
const SimpleTable = ({ classes }) => {
const [routes, setRoutes] = useState([]);
const [loading, setLoading] = useState(true);
const fetchAllOrders = async () => {
const result = await getOrdersBasedOnRouteQuery();
if (!result.loading) {
setRoutes(result.data.route);
setLoading(false);
}
};
useEffect(() => {
fetchAllOrders();
}, [loading === true]);
if (loading) {
return <div>Loading...</div>;
}
return (
<Paper className={classes.root}>
<Table>
<TableHead>
<TableRow>
<TableCell>Reference</TableCell>
<TableCell numeric>Customer Name</TableCell>
<TableCell numeric>Total</TableCell>
<TableCell numeric>Status</TableCell>
<TableCell numeric>Created At</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableGroup classes={classes} routes={routes} groupProperty="name" />
</TableBody>
</Table>
</Paper>
);
};
SimpleTable.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleTable);

Related

Put two backgroundcolor on two lines only

How can I put two color backgrounds on two different lines?
I managed to set it up on a row before click on a table row and I would like to put a second backgroundcolor on another row when a condition is met
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import {TableBody, Table, TableCell, TableContainer, TableHead, TableRow, Paper} from "#material-ui/core";
import { useState } from "react";
const useStyles = makeStyles({
table: {
minWidth: 650
},
tableRow: {
"&$selected, &$selected:hover": {
backgroundColor: "#E8E8E8"
}
},
hover: {},
selected: {}
});
function createData(name, calories, fat, carbs, protein) { return { name, calories, fat, carbs, protein }; }
const rows = [ createData("Frozen yoghurt", 159, 6.0, 24, 4.0), createData("Ice cream sandwich", 237, 9.0, 37, 4.3), createData("Eclair", 262, 16.0, 24, 6.0), createData("Cupcake", 305, 3.7, 67, 4.3), createData("Gingerbread", 356, 16.0, 49, 3.9) ];
export default function SimpleTable() {
const classes = useStyles();
const [selectedIndex, setSelectedIndex] = useState(null);
const val = false;
const secondRow = 0;
const selectRow = (i) => {
setSelectedIndex(i);
if (val) {
// put a backgroundcolor on line 1
}
};
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row, index) => (
<TableRow hover key={row.name} onClick={() => {selectRow(index);}} selected=selectedIndex === index} classes={{ hover: classes.hover, selected: classes.selected }} className={classes.tableRow} >
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">{row.calories}</TableCell>
<TableCell align="right">{row.fat}</TableCell>
<TableCell align="right">{row.carbs}</TableCell>
<TableCell align="right">{row.protein}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
https://codesandbox.io/s/material-demo-forked-5u4jz?file=/demo.js
You can assign an array as your state for it to contain the selected indices. In the example below, I used shift on the array to retain the latest selection, remove the oldest one, and push the new one.
const [selectedIndex, setSelectedIndex] = useState([]);
const selectRow = (i) => {
// checks to see if it's already selected
if (selectedIndex.includes(i)) {
return;
}
let newSelected = [...selectedIndex];
// sample logic for the "only 2 rows selected" requirement
if (newSelected.length === 2) {
newSelected.shift();
newSelected.push(i);
} else {
newSelected.push(i);
}
setSelectedIndex(newSelected);
};
<TableRow
onClick={() => {
selectRow(index);
}}
selected={selectedIndex.includes(index)}
>
https://codesandbox.io/s/material-demo-forked-h5i77?file=/demo.js

How to display state object elements in another component?

i'm trying to use a table from MaterialUI and populate it with financial data (using promise API). I have three components:
Gl.js
myTable
index.js
I want to use the state object in the Gl.js component and populate the table in myTable.js but not sure how to. Please ask for more details if necessary, I must complete this project.
GL.js
import React, { Component, createContext, Provider } from 'react';
import ReactDOM from 'react-dom';
import axios from "axios";
import CollapsibleTable from './myTable';
export const CTX = React.createContext();
class Gl extends React.Component {
_isMounted = false;
constructor(props) {
super(props)
this.state = {
applBs: []
}
}
getData() {
const axios = require("axios");
axios({
"method": "GET",
"url": "https://fmpcloud.p.rapidapi.com/balance-sheet-statement/AAPL",
"headers": {
"content-type": "application/octet-stream",
"x-rapidapi-host": "fmpcloud.p.rapidapi.com",
"x-rapidapi-key": "4560d76562msh36c4de0a03c6e54p1bf4a2jsne2d882693304",
"useQueryString": true
}, "params": {
"period": "annual",
"apikey": "demo"
}
})
.then(response => {
if (this._isMounted) {
this.setState({ applBs: response.data[0] })
}
})
.catch(error => {
console.log(error)
})
}
componentDidMount() {
this._isMounted = true;
this.getData();
}
componentWillUnamount() {
this._isMounted = false;
}
render() {
return (
<div>
<CollapsibleTable callData={this.state.applBs} />
<CTX.Provider value={ this.state.applBs }>
{this.props.children}
</CTX.Provider>
</div>
)
}
}
ReactDOM.render(<Gl />, document.getElementById("root"))
export default Gl
myTable.js
import React, { Component, Consumer } from 'react';
import ReactDOM from "react-dom"
import PropTypes from 'prop-types';
import { makeStyles } from '#material-ui/core/styles';
import Box from '#material-ui/core/Box';
import Collapse from '#material-ui/core/Collapse';
import IconButton from '#material-ui/core/IconButton';
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 Typography from '#material-ui/core/Typography';
import Paper from '#material-ui/core/Paper';
import KeyboardArrowDownIcon from '#material-ui/icons/KeyboardArrowDown';
import KeyboardArrowUpIcon from '#material-ui/icons/KeyboardArrowUp';
import CTX from "./GL.js"
const useRowStyles = makeStyles({
root: {
'& > *': {
borderBottom: 'unset',
},
},
});
function createData(name, calories, fat, carbs, protein, price) {
return {
name,
calories,
fat,
carbs,
protein,
price,
history: [
{ lineItem: 'Pop', date: '2020-01-05', customerId: '11091700', amount: 3 },
{ lineItem: 'Pop', date: '2020-01-02', customerId: 'Anonymous', amount: 1 },
],
};
}
function Row(props) {
const { row } = props;
const [open, setOpen] = React.useState(false);
const classes = useRowStyles();
return (
<React.Fragment>
<TableRow className={classes.root}>
<TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">{row.calories}</TableCell>
<TableCell align="right">{row.fat}</TableCell>
<TableCell align="right">{row.carbs}</TableCell>
<TableCell align="right">{row.protein}</TableCell>
</TableRow>
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>
Line Item
</TableCell>
<TableCell>
Google
</TableCell>
<TableCell>
Customer
</TableCell>
<TableCell align="right">
Amount
</TableCell>
<TableCell align="right">
Total price ($)
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{row.history.map((historyRow) => (
<TableRow key={historyRow.date}>
<TableCell component="th" scope="row">
{historyRow.date}
</TableCell>
<TableCell>{historyRow.customerId}</TableCell>
<TableCell align="right">{historyRow.amount}</TableCell>
<TableCell align="right">
{Math.round(historyRow.amount * row.price * 100) / 100}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
}
Row.propTypes = {
row: PropTypes.shape({
calories: PropTypes.number.isRequired,
carbs: PropTypes.number.isRequired,
fat: PropTypes.number.isRequired,
history: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.number.isRequired,
customerId: PropTypes.string.isRequired,
date: PropTypes.string.isRequired,
}),
).isRequired,
name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
protein: PropTypes.number.isRequired,
}).isRequired,
};
const rows = [
createData('Frozen yoghurt', 159, 6.0, 24, 4.0, 3.99),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3, 4.99),
createData('Eclair', 262, 16.0, 24, 6.0, 3.79),
createData('Cupcake', 305, 3.7, 67, 4.3, 2.5),
createData('Gingerbread', 356, 16.0, 49, 3.9, 1.5),
];
export default function CollapsibleTable() {
return (
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableHead>
<TableRow>
<TableCell />
<TableCell>
Apple.Inc
</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<Row key={row.name} row={row} />
))}
</TableBody>
</Table>
</TableContainer>
);
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Gl from './GL';
import CollapsibleTable from './myTable';
ReactDOM.render(
<React.StrictMode>
<Gl >
<CollapsibleTable />
</Gl>
</React.StrictMode>,
document.getElementById('root'));
ok then this must be the issue be clear with class and functional component this keyword can be used only in class component!!
check this link for further reference link
in your case have a console in
<TableContainer component={Paper}>
{console.log('callData', props.callData)}
<Table aria-label="collapsible table">
you will get the value of callData use that to display in table

Material Ui table reduce the space between columns

I have a table created with ReactJs & Material Ui like the code below.
Her a live test: https://codesandbox.io/s/material-demo-692nz?file=/demo.js
I want to reduce the space between columns, there is always big space after first column no matter how many columns i add after it. It's like they have some 'space-between' style but cannot remove it.
Any tips ? thank you
import React from "react";
import { 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 useStyles = makeStyles({
table: {
minWidth: 50
}
});
function createData(name, calories, fat, carbs, protein) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
createData("Eclair", 262, 16.0, 24, 6.0),
createData("Cupcake", 305, 3.7, 67, 4.3),
createData("Gingerbread", 356, 16.0, 49, 3.9)
];
export default function SimpleTable() {
const classes = useStyles();
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="left">Dessert (100g serving)</TableCell>
<TableCell align="left">Calories</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => (
<TableRow key={row.name}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="left">{row.calories}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
Using inline-style, add width to <TableCell /> under <TableHead /> would be fine
<TableCell align="left" style={{width: 200}}>Dessert (100g serving)</TableCell>
Update:
There are multiple ways to define the width style
style={{width: '20vw'}}
or
style={{minWidth: 200}}
may work for the style requests.

Material UI React Table onCellClick

I am trying to implement a simple onCellClick listener on Material UI table.
In earlier versions of it, a function in the table scope onCellClick used to give the row and column number where click was made as shown here
Currently when this function is placed -
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } 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 TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import Paper from '#material-ui/core/Paper';
const styles = {
}
let id = 0;
function createData(name, calories, fat, carbs, protein) {
id += 1;
return { id, name, calories, fat, carbs, protein };
}
const rows = [
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Gingerbread', 356, 16.0, 49, 3.9),
];
function SimpleTable(props) {
const { classes } = props;
return (
<Paper className={classes.root}>
<Table className={classes.table}
onCellClick={(rowNumber,
columnId) =>
console.log(rowNumber,columnId)}>
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell numeric>Calories</TableCell>
<TableCell numeric>Fat (g)</TableCell>
<TableCell numeric>Carbs (g)</TableCell>
<TableCell numeric>Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => {
return (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell numeric>{row.calories}</TableCell>
<TableCell numeric>{row.fat}</TableCell>
<TableCell numeric>{row.carbs}</TableCell>
<TableCell numeric>{row.protein}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Paper>
);
}
export default withStyles(styles)(SimpleTable);
it throws the error Unknown event handler property onCellClick. It will be ignored.This is expected because unlike previous versions no onCellClick function is passed in the table source code.
How to achieve onCellClick functionality now in Material-UI?
Any help will be highly appreciated.
A cell can be a th or td element (see the source code) or a custom element that you pass through the component property.
Each of these will have support for the onClick property.
So you need something like this:
handleClick = (id, column) => {
return (event) => {
console.log(`You clicked on row with id ${id}, in column ${column}.`);
}
}
render() {
return (
// ...
{this.state.rows.map((row) => (
<TableRow key={row.id}>
<TableCell onClick={this.handleClick(row.id, "calories")}>
{row.calories}
</TableCell>
// ...
<TableCell onClick={this.handleClick(row.id, "protein")}>
{row.protein}
</TableCell>
</TableRow>
)}
// ...
);
}

TypeError: Cannot read property 'root' of undefined

I'm trying to put a BasicTable function from Material-Ui to my React.js file. Here is my code.
import React, { Component } from 'react';
import { Route, Redirect, Switch, Link, HashRouter} from 'react-router-dom';
import firebase, { auth, provider } from '../firebase.js';
import '../App.css';
// Material-ui theme
import NavBar from '../profile_pages/navBar';
//For Table Material-ui
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Table, { TableBody, TableCell, TableHead, TableRow } from 'material-ui/Table';
import Paper from 'material-ui/Paper';
const styles = theme => ({
root: {
width: '100%',
marginTop: theme.spacing.unit * 3,
overflowX: 'auto',
},
table: {
minWidth: 700,
},
});
let id = 0;
function createData(name, calories, fat, carbs, protein) {
id += 1;
return { id, name, calories, fat, carbs, protein };
}
const data = [
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Gingerbread', 356, 16.0, 49, 3.9),
];
function BasicTable(props) {
const { classes } = props;
return (
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell numeric>Calories</TableCell>
<TableCell numeric>Fat (g)</TableCell>
<TableCell numeric>Carbs (g)</TableCell>
<TableCell numeric>Protein (g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(n => {
return (
<TableRow key={n.id}>
<TableCell>{n.name}</TableCell>
<TableCell numeric>{n.calories}</TableCell>
<TableCell numeric>{n.fat}</TableCell>
<TableCell numeric>{n.carbs}</TableCell>
<TableCell numeric>{n.protein}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Paper>
);
}
class Charity extends Component {
constructor() {
super()
this.state = {
open: false
}
}
//For nav
handleToggle() {
this.setState({
open: !this.state.open
})
}
render() {
return (
<div>
<NavBar
onToggle={() => this.handleToggle()}
open={this.state.open}
/>
{<BasicTable/>}
</div>
);
}
}
BasicTable.propTypes = {
classes: PropTypes.object.isRequired,
};
export default Charity;
Now I have some errors as following.
<BasicTable>
42 | const { classes } = props;
43 |
44 | return (
> 45 | <Paper className={classes.root}>
46 | <Table className={classes.table}>
47 | <TableHead>
48 | <TableRow>
<./src/index.js>
8 | //make click events enable to use
9 | injectTapEventPlugin();
10 |
> 11 | ReactDOM.render(<Root/>, document.getElementById('root'));
12 | registerServiceWorker();
13 |
14 |
What I'm stacking on the action is about the way to call the BasicTable(props) function at the render of Charity class.
How should I resolved the error?
The BasicTable() function is brought from an example of Material-ui website (https://material-ui-next.com/demos/tables/).
Then I put the code to my one without any changes.
You props does not contain classes
If you want to access classes that are in the styles constant, then you might want to do this styles(/*your theme name/*).root
const { classes } = props; doing this is assigning classes=undefined then when you are trying to access classes.root it it throwing the error.
Now, you can either change this
<Paper className={classes.root}>
<Table className={classes.table}>
TO
// Because the theme argument is never used in the function
<Paper className={styles("").root}>
<Table className={styles("").table}>
OR change this line in Charity component
{<BasicTable />}
TO
{<BasicTable classes={styles("")}/>} given styles

Resources