Created
June 20, 2018 11:19
-
-
Save simform-solutions/2614bcf43ca1a0c7a23ac8c25352e073 to your computer and use it in GitHub Desktop.
Material DataTable component with Dynamic data and Event Handlers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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