Skip to content

Instantly share code, notes, and snippets.

@simform-solutions
Created June 20, 2018 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simform-solutions/2614bcf43ca1a0c7a23ac8c25352e073 to your computer and use it in GitHub Desktop.
Save simform-solutions/2614bcf43ca1a0c7a23ac8c25352e073 to your computer and use it in GitHub Desktop.
Material DataTable component with Dynamic data and Event Handlers
import React from 'react';
import classNames from 'classnames';
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 TablePagination from '@material-ui/core/TablePagination';
import TableRow from '@material-ui/core/TableRow';
import TableSortLabel from '@material-ui/core/TableSortLabel';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Paper from '@material-ui/core/Paper';
import Checkbox from '@material-ui/core/Checkbox';
import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import DeleteIcon from '@material-ui/icons/Delete';
import FilterListIcon from '@material-ui/icons/FilterList';
import { lighten } from '@material-ui/core/styles/colorManipulator';
import InfoIcon from '@material-ui/icons/Info';
import EditIcon from '@material-ui/icons/Edit';
import VisibilityIcon from '@material-ui/icons/Visibility';
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
const selectStyles = theme => ({
selectRoot : {
color: theme.palette.text.secondary,
fontSize: '0.75rem',
fontWeidht: '500',
}
});
let StyledSelect = ({classes, children,...otherProps}) => (
<Select
{...otherProps}
classes = {{
root: classes.selectRoot,
}}
>
{children}
</Select>
);
StyledSelect = withStyles(selectStyles)(StyledSelect);
class EnhancedTableHead extends React.Component {
createSortHandler = property => event => {
this.props.onRequestSort(event, property);
};
render() {
const {
onSelectAllClick,
order,
orderBy,
numSelected,
rowCount,
columnData,
columnConfig,
columnChanger,
showActions,
} = this.props;
return (
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
indeterminate={numSelected > 0 && numSelected < rowCount}
checked={numSelected === rowCount}
onChange={onSelectAllClick}
/>
</TableCell>
{columnData.map(column => {
let columnOptions = columnConfig && columnConfig[column.id];
if(columnOptions && columnOptions.length) {
return (
<TableCell
key={column.id}
numeric={ column.numeric === undefined ? true : column.numeric}
padding={ column.disablePadding ? 'none' : 'default'}
>
<StyledSelect
value={columnConfig[column.id][0].id}
onChange={(event)=>{columnChanger(column.id,event.target.value)}}
disableUnderline
name="Scope"
>
{
columnOptions.map((option)=>
<MenuItem key={option.id} value={option.id}>{option.label}</MenuItem>
)
}
</StyledSelect>
</TableCell>
)
}
return (
<TableCell
key={column.id}
numeric={ column.numeric === undefined ? true : column.numeric}
padding={ column.disablePadding ? 'none' : 'default'}
sortDirection={orderBy === column.id ? order : false}
>
<Tooltip
title="Sort"
placement={column.numeric ? 'bottom-end' : 'bottom-start'}
enterDelay={300}
>
<TableSortLabel
active={orderBy === column.id}
direction={order}
onClick={this.createSortHandler(column.id)}
>
{column.label}
</TableSortLabel>
</Tooltip>
</TableCell>
);
})
}
{showActions &&
<TableCell padding = 'none'>
Actions
</TableCell>
}
</TableRow>
</TableHead>
);
}
}
EnhancedTableHead.propTypes = {
numSelected: PropTypes.number.isRequired,
classes: PropTypes.object.isRequired,
onRequestSort: PropTypes.func.isRequired,
onSelectAllClick: PropTypes.func.isRequired,
order: PropTypes.string.isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired
};
const toolbarStyles = theme => ({
root: {
paddingRight: theme.spacing.unit
},
highlight:
theme.palette.type === 'light'
? {
color: theme.palette.secondary.main,
backgroundColor: lighten(theme.palette.secondary.light, 0.85)
}
: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.secondary.dark
},
spacer: {
flex: '1 1 100%'
},
actions: {
color: theme.palette.text.secondary
},
title: {
flex: '0 0 auto'
}
});
const styles = theme => ({
root: {
width: '100%',
marginTop: theme.spacing.unit * 3
},
table: {
minWidth: 1020
},
tableWrapper: {
overflowX: 'auto'
}
});
class EnhancedTable extends React.Component {
constructor(props) {
super(props);
this.state = {
order: 'asc',
orderBy: 'calories',
selected: [],
page: 0,
rowsPerPage: 5
};
}
handleRequestSort = (event, property) => {
const orderBy = property;
let order = 'desc';
if (this.state.orderBy === property && this.state.order === 'desc') {
order = 'asc';
}
const data =
order === 'desc'
? this.state.data.sort((a, b) => (b[orderBy] < a[orderBy] ? -1 : 1))
: this.state.data.sort((a, b) => (a[orderBy] < b[orderBy] ? -1 : 1));
this.setState({ data, order, orderBy });
};
handleSelectAllClick = (event, checked) => {
if (checked) {
this.setState({ selected: this.state.data.map(n => n.id) });
return;
}
this.setState({ selected: [] });
};
handleInfoClick = (event, id) => {
console.log(id);
event.stopPropagation();
}
handleClick = (event, id) => {
const { selected } = this.state;
const selectedIndex = selected.indexOf(id);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
this.setState({ selected: newSelected });
};
handleChangePage = (event, page) => {
this.setState({ page });
};
handleChangeRowsPerPage = event => {
this.setState({ rowsPerPage: event.target.value });
};
isSelected = id => this.state.selected.indexOf(id) !== -1;
render() {
const { classes, data, columnData, columnConfig, rowAction, showActions } = this.props; //columnData, columnConfig
//this had data
const { order, orderBy, selected, rowsPerPage, page } = this.state;
const emptyRows =
rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage);
return (
<Paper className={classes.root}>
{/* <EnhancedTableToolbar numSelected={selected.length} /> */}
<div className={classes.tableWrapper}>
<Table className={classes.table} aria-labelledby="tableTitle">
<EnhancedTableHead
//columnData = {columnData}
//columnConfig = {columnConfig}
{...this.props}
numSelected={selected.length}
order={order}
orderBy={orderBy}
onSelectAllClick={this.handleSelectAllClick}
onRequestSort={this.handleRequestSort}
rowCount={data.length}
/>
<TableBody>
{data
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((n,index) => {
const isSelected = this.isSelected(n.id);
return (
<TableRow
hover
//onClick={event => this.handleClick(event, n.id)}
role="checkbox"
aria-checked={isSelected}
tabIndex={-1}
key={n.id}
selected={isSelected}
>
<TableCell padding="checkbox">
<Checkbox checked={isSelected} />
</TableCell>
{columnData.map((colItem,index)=>{
return (
index === 0 ?
<TableCell
scope="row"
padding="none"
key={colItem.id}
numeric={ colItem.numeric === undefined ? true : colItem.numeric}
>
{n[colItem.id]}
</TableCell> :
<TableCell
key={colItem.id}
numeric
numeric={ colItem.numeric === undefined ? true : colItem.numeric}
>
{n[colItem.id]}
</TableCell>
);
})
}
{showActions &&
<TableCell >
<IconButton onClick={ event => rowAction('edit',n.id,index)}>
<EditIcon />
</IconButton>
<IconButton onClick={ event => rowAction('info',n.id,index)}>
<InfoIcon />
</IconButton>
<IconButton onClick={ event => event => rowAction('visibility',n.id,index)}>
<VisibilityIcon />
</IconButton>
</TableCell>
}
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 49 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</div>
<TablePagination
component="div"
count={data.length}
rowsPerPage={rowsPerPage}
page={page}
backIconButtonProps={{
'aria-label': 'Previous Page'
}}
nextIconButtonProps={{
'aria-label': 'Next Page'
}}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleChangeRowsPerPage}
/>
</Paper>
);
}
}
EnhancedTable.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(EnhancedTable);
render(){
<DataTable
columnConfig = {columnConfig}
columnChanger= {this.columnChanger}
data = {tableData}
columnData = {columnData}
showActions
rowAction = {this.handleTableRowAction}
/>
}
handleTableRowAction = (actionType, itemId, index ) => {
switch(actionType){
case 'edit':
break;
case 'info':
this.setState({
infoForId: itemId,
},this.toggleDrawer);
break;
case 'visibility':
break;
default:
return;
}
}
columnChanger = (colKey,value) => {
console.log(value,' clicked');
}
export const columnData = [
{
id: 'name',
disablePadding: true,
label: 'Audience Name',
numeric: false,
},
{ id: 'calories', numeric: true, label: 'Mapping' },
{ id: 'fat', numeric: true, label: 'Last Editor' },
{ id: 'carbs', numeric: true, label: 'Edited' },
{ id: 'protein', label: 'protein' },
];
export const columnConfig = {
calories: [
{
id: 'calories', numeric: true, label: 'Calories',
},{
id: 'kiloCalories', numeric: true, label: 'Kcal',
}
],
fat: [
{
id: 'fat', numeric: true, label: 'Fat'
},{
id: 'fatContent', numeric: true, label: 'Fat Content'
}
]
};
let counter = 0;
function createData(name, calories, fat, carbs, protein) {
counter += 1;
return { id: counter, name, calories, fat, carbs, protein };
}
export const getData = () => {
let data = [
createData('Cupcake', 305, 3.7, 67, 4.3),
createData('Donut', 452, 25.0, 51, 4.9),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Gingerbread', 356, 16.0, 49, 3.9),
createData('Honeycomb', 408, 3.2, 87, 6.5),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Jelly Bean', 375, 0.0, 94, 0.0),
createData('KitKat', 518, 26.0, 65, 7.0),
createData('Lollipop', 392, 0.2, 98, 0.0),
createData('Marshmallow', 318, 0, 81, 2.0),
createData('Nougat', 360, 19.0, 9, 37.0),
createData('Oreo', 437, 18.0, 63, 4.0)
];
return data;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment