I have created a Table with React and MUI, and tried to implement a sorting function for each column in ascending and descending way.
But when I click on the header to sort the column, I get an error, that says "Data is not iterable" in the console, and I have not been able to figure out where the mistake is.
import React, {useEffect, useState} from 'react';
import Table from '#mui/material/Table';
import TableBody from '#mui/material/TableBody';
import TableCell from '#mui/material/TableCell';
import TableContainer from '#mui/material/TableContainer';
import TableHead from '#mui/material/TableHead';
import TableRow from '#mui/material/TableRow';
import Paper from '#mui/material/Paper';
import TableSortLabel from "#mui/material/TableSortLabel";
import TablePagination from '#mui/material/TablePagination';
import { createStyles, TextField } from '#mui/material';
import "./table.css";
function createUserData (fullname, email, nationality, city){
return {fullname, email, nationality, city};
}
const rows= [];
export default function RandomUserTable(){
const [data, setData]= useState([]);
// const [rowData, setRowData]= useState(rows);
// const [orderDirection, setOrderDirection]= useState("asc");
const [order, setOrder]=useState('asc');
const [searchTerm, setSearchTerm]= useState('');
const [page, setPage] =useState(0);
const [rowsPerPage, setRowsPerPage] =useState(10);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
useEffect(()=>{
fetch('https://randomuser.me/api/?results=30')
.then((response) => {
return response.json();
})
.then((data) => {
setData(data);
console.log(data);
});
}, []);
const sorting=(col)=>{
if(order==='asc'){
const sorted= [...data].sort((a,b)=>
a[col].toLowerCase()>b[col].toLowerCase()?1:-1
);
setData(sorted);
setOrder('dsc')
}
if(order==='dsc'){
const sorted= [...data].sort((a,b)=>
a[col].toLowerCase()<b[col].toLowerCase()?1:-1
);
setData(sorted);
setOrder('asc')
}
}
// const sortArray= (arr, orderBy)=> {
// switch (orderBy){
// case "asc":
// return [...arr].sort ((a,b)=>
// a.city> b.city? 1:b.city > a.city? -1:0
// );
// case "desc":
// return [...arr].sort((a, b)=>
// a.city < b.city ? 1 : b.city< a.city ? -1 : 0
// );
// }
// };
// const handleSortRequest = ()=>{
// setRowData(sortArray(rows, orderDirection));
// setOrderDirection(orderDirection === "asc"? "desc":"asc");
// }
return (
<>
<TextField sx={{ width: 660, marginBottom: "2rem", marginTop: "2rem", border: "2px solid violet" }} className="text-field" onChange={event=>{setSearchTerm(event.target.value)}} placeholder="Search..."></TextField>
<TableContainer component={Paper} sx={{width:800, margin: "0 auto"}}>
<Table stickyHeader className="table" aria-label="simple table">
<TableHead>
<TableRow sx={{'& .MuiTableCell-root':{backgroundColor:"rgb(120, 169, 233)", border: "1px solid white", color: 'white'}}}>
<TableCell align="center">Fullname</TableCell>
<TableCell onClick={()=>sorting("email")} align="center">E-Mail</TableCell>
<TableCell onClick={()=>sorting("nat")} align="center">Nationality</TableCell>
{/* <TableCell align="center" onClick={handleSortRequest}> */}
<TableCell align="center">
<TableSortLabel style={{color: 'white'}} active={true}>City</TableSortLabel>
{/* <TableSortLabel style={{color: 'white'}} active={true} direction={orderDirection}>City</TableSortLabel> */}
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.results?.slice(page*rowsPerPage, page*rowsPerPage+rowsPerPage).filter((val)=>{
if(searchTerm=== ""){
return val
}else if(val.nat.toLowerCase().includes(searchTerm.toLowerCase()) ){
return val
}else if(val.email.toLowerCase().includes(searchTerm.toLowerCase())){
return val
}else if(val.location.city.toLowerCase().includes(searchTerm.toLowerCase())){
return val
}
}).map((user,index) => (
<TableRow key={index} sx={{'& .MuiTableCell-root':{backgroundColor: 'rgba(54, 96, 129, 0.241)', height: '3rem'}}}>
<TableCell align="center" component="th" scope="row">
{ (user.name.first)+ " " +(user.name.last)}
</TableCell>
<TableCell align="center">{user.email}</TableCell>
<TableCell align="center">{user.nat}</TableCell>
<TableCell align="center">{user.location.city}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</>
);
}
enter image description here
you cant spread object in the array like this
let data= {info:0,result:[1,2,3]}
let spread = [...data]
that's why you get an error "Data is not iterable"
do this instead
const sorting=(col)=>{
if(order==='asc'){
const sorted= {...data,["results"]:data.results.sort((a,b)=>
a[col].toLowerCase()>b[col].toLowerCase()?1:-1
)}
setData(sorted);
setOrder('dsc')
}
if(order==='dsc'){
const sorted= {...data,["result"]: data.results.sort((a,b)=>
a[col].toLowerCase()<b[col].toLowerCase()?1:-1
)}
setData(sorted);
setOrder('asc')
}
}
Okay so I have a really strange error in my react application.
Basically I have a function that handles an input change and changes the state from the parent component.
import React from "react";
import PaginationExtended from "../PaginationExtended/PaginationExtended";
import { ScreenContext } from "../../helpers/context";
import {
Paper,
TableCell,
TableContainer,
Table,
TableBody,
TableHead,
TableRow,
Checkbox,
TextField,
} from "#material-ui/core";
import EnhancedTableToolbar from "../EnhancedToolBar/EnhancedToolBar";
import uuid from "react-uuid";
import findWithAttr from "../../helpers/findAttr";
import objectInArray from "../../helpers/objectInArray";
import ItemTableRow from "./ItemTableRow/ItemTableRow";
const ItemTable = (props) => {
const screen = React.useContext(ScreenContext);
const handleCheckboxClick = (e) => {
if (e.target.checked) {
props.setDynamicRows((prevState) => {
const newTableData = [...prevState];
console.log(newTableData);
const rowIndex = findWithAttr(props.rows, "id", parseInt(e.target.id));
const newRow = {};
props.headings.forEach((heading) => {
newRow[heading.text.toLowerCase()] =
props.rows[rowIndex][heading.default];
});
newRow.id = e.target.id;
newRow.type = "accepted";
newRow.files = [];
newRow.category = props.title;
newTableData.push(newRow);
return newTableData;
});
} else {
props.setDynamicRows((prevState) => {
const newTableData = [...prevState];
console.log(newTableData);
const rowIndex = findWithAttr(
newTableData,
"id",
parseInt(e.target.id)
);
newTableData.splice(rowIndex, 1);
return newTableData;
});
}
};
const handleInputChange = () => {
console.log(1);
props.setDynamicRows((prevState) => {
const newTableData = [...prevState];
console.log(newTableData);
const rowIndex = findWithAttr(newTableData, "id", props.row.id);
newTableData[rowIndex][e.target.name] = e.target.value;
return newTableData;
});
};
return (
<Paper className={`${props.className}`}>
<EnhancedTableToolbar
screen={screen}
title={props.title}
// record={props.rows}
// setRows={setRows}
/>
<TableContainer>
<Table aria-label="simple table">
<TableHead>
<TableRow>
{props.hasCheckbox && <TableCell padding="checkbox" />}
{props.headings.map((heading) => {
return (
<TableCell className={"text-nowrap"} align="right">
{heading.text}
</TableCell>
);
})}
</TableRow>
</TableHead>
<TableBody>
{props.rows.map((row, index) => {
if (!props.inputTable) {
return (
<ItemTableRow
title={props.title}
headings={props.headings}
handleCheckboxClick={handleCheckboxClick}
dynamicRows={props.dynamicRows}
index={index}
row={row}
hasCheckbox={props.hasCheckbox}
setDynamicRows={props.setDynamicRows}
/>
);
} else {
if (row.type === "accepted" && row.category === props.title) {
return (
<ItemTableRow
title={props.title}
headings={props.headings}
handleCheckboxClick={handleCheckboxClick}
dynamicRows={props.dynamicRows}
index={index}
row={row}
hasCheckbox={props.hasCheckbox}
handleInputChange={handleInputChange}
/>
);
}
}
})}
</TableBody>
</Table>
</TableContainer>
{props.hasPagination && (
<PaginationExtended
recordsPerPage={rowsPerPage}
className={"p-3 justify-content-end"}
totalRecords={rows.length}
paginate={handleChangePage}
currentPage={page}
shape={"round"}
/>
)}
</Paper>
);
};
export default ItemTable;
This function is called from a child component of the component at the top.
import React from "react";
import { TableCell, TableRow, Checkbox, TextField } from "#material-ui/core";
import objectInArray from "../../../helpers/objectInArray";
const ItemTableRow = (props) => {
return (
<TableRow key={props.index}>
{props.hasCheckbox && (
<TableCell padding="checkbox">
<Checkbox
id={props.row.id}
checked={objectInArray(
props.dynamicRows,
"id",
props.row.id.toString()
)}
onClick={props.handleCheckboxClick}
// inputProps={{
// "aria-labelledby": `${props.title}-${index}`,
// }}
/>
</TableCell>
)}
{props.headings.map((heading) => {
return (
<TableCell
className={"text-nowrap"}
id={`${props.title}-${props.index}`}
align="right"
>
{heading.isTextInput ? (
<TextField
onChange={props.handleInputChange}
id={`${props.title}-${heading.text}-${props.row.id}`}
type={heading.inputType}
size={"small"}
variant="outlined"
inputProps={{ min: 0 }}
notched={false}
InputLabelProps={{ shrink: false }}
className={`minInputWidth`}
InputProps={{
classes: { input: "py-2 customize-inputField" },
}}
name={heading.text.toLowerCase()}
placeholder={heading.text}
/>
) : (
<p>{props.row[heading.default]}</p>
)}
</TableCell>
);
})}
</TableRow>
);
};
export default ItemTableRow;
When I trigger this event the following error appears in the console.
Uncaught TypeError: props.setDynamicRows is not a function
The curious thing about this is that the handleCheckboxClick function does not throw any error and is also called called from the child component. I have tried reestructuring the components and functions but nothing works.
If someone knows what is happening I would really appreciate the help, thanks.
I'm trying to recover the selected item on array of elements, I have an API service which returns a list of 5 jobs and a page on React to display the applicants. The rendered table from the list has a menu button for each row, when I click on the menu button it fires the handleMenuOpen event and returns the index of the selected job, but when the See applicants menuItem is clicked the handleSeeApplicantsClick event is fired and the returned value is always 4 (the index of the last job) can you please help me with this?
Thanks in advance
import { useState, useEffect } from 'react';
import ApiService from '../../services/ApiService';
export default function Evaluation(props) {
const [jobs, setJobs] = useState([]);
const [selected, setSelected] = useState(null);
const [anchorEl, setAnchorEl] = useState(null);
const columns = [
{label: 'Description', minWidth: 220, width: 200,},
{label: '', minWidth: 20, width: 20},
];
const loadJobs = async() => {
const result = await ApiService.get('/u/jobs');
setJobs(result.data || []);
};
const loadSelectedJob = async(jobId) => {
const result = await ApiService.get('/u/job/'+jobId);
setSelected(result);
};
useEffect( async() => {
if(!jobs?.length) loadJobs();
}, []);
const handleSeeApplicantsClick = (i) => {
console.log(i);
setAnchorEl(null);
};
const handleMenuOpen = (e, i) => {
console.log(i);
setAnchorEl(e?.currentTarget);
}
return (<div>
<TableContainer component={Paper}>
<Table stickyHeader>
<TableHead>
<TableRow>
{ columns.map((x, i) => <TableCell key={i}>{ x.label }</TableCell>) }
</TableRow>
</TableHead>
<TableBody>
{jobs.map( (x, j) => <TableRow key={x.id} >
<TableCell>
<Typography variant="body2">{ x.description }</Typography>
</TableCell>
<TableCell>
<IconButton onClick={ (e) => handleMenuOpen(e, i) }>
<MenuIcon />
</IconButton>
<Menu anchorEl={anchorEl} open={ Boolean(anchorEl) } onClose={() => handleMenuOpen(null)}>
<MenuItem onClick={ (ex) => { handleSeeApplicantsClick(i) }}>See applicants</MenuItem>
</Menu>
</TableCell>
</TableRow> )}
</TableBody>
</Table>
</TableContainer>
</div>);
}
Edit:
As suggested I've changed the code like this
<IconButton onClick={ (e) => handleMenuOpen(e, j) }>
<MenuIcon />
</IconButton>
But it does not fix the error, the last index is always returned.
Change handleMenuOpen(e, i) to handleMenuOpen(e, j)
i is the final value of your previous columns.map(x, i) whereas you are rendering using jobs.map( (x, j))
change <IconButton onClick={ (e) => handleMenuOpen(e, i) }> to <IconButton onClick={ (e) => handleMenuOpen(e, j) }>
change the function param <IconButton onClick={ (e) => handleMenuOpen(e, i) }>
to <IconButton onClick={ (e) => handleMenuOpen(e, j) }> because in map index value is setting into j, you need to access from j, in your example...
<TableBody>
{jobs.map( (x, j) => <TableRow key={x.id} >
<TableCell>
<Typography variant="body2">{ x.description }</Typography>
</TableCell>
<TableCell>
<IconButton onClick={ (e) => handleMenuOpen(e, i) }>
<MenuIcon />
</IconButton>
<Menu anchorEl={anchorEl} open={ Boolean(anchorEl) } onClose={() => handleMenuOpen(null)}>
<MenuItem onClick={ (ex) => { handleSeeApplicantsClick(i) }}>See applicants</MenuItem>
</Menu>
</TableCell>
</TableRow> )}
</TableBody>
or for best approch you can handle this through by your unique id {x.id} if its unique
My design currently stands like this
I am using Material UI's radio button, i want to make each row select able just once. When i add a <RadioButton> component, i am able to select it but however i am not able to toggle between rows
transactionRow(member: Object) {
return (
<tr id='drawLotteryTabel' style={styles.tr} key={member.uuid}>
<td className="col-md-2 col-xs-2">{member.user.fullName}</td>
<td className="col-md-1 col-xs-1">{this.getSubscriptionDropDown(member.subscriptions)}</td>
<td className="col-md-2 col-xs-2">{CommonConstants.INR_SYMBOL + ' ' + Utils.formatNumberLocalised(member.bidDiscountAmount || 0)}</td>
<td className="col-md-2 col-xs-2">{CommonConstants.INR_SYMBOL + ' ' + Utils.formatNumberLocalised(member.bidDiscountPercent || 0)}</td>
<td className="col-md-2 col-xs-2">{CommonConstants.INR_SYMBOL + ' ' + Utils.formatNumberLocalised(member.unpaidAmount || 0)}</td>
<td
className="col-md-2 col-xs-2"
>
<RadioButtonGroup name="shipSpeed" defaultSelected="not_light" key={member.uuid}>
<RadioButton
value="light"
style={styles.radioButton}
/>
</RadioButtonGroup></td>
</tr>
);
}
The Above code results in something like this
What should i do so that i get the entire table row as a single entity to select.
You'll probably, unfortunately, need to manage the state of your radio buttons manually, as a controlled component.
Have the RadioButtonGroup include a call to an onChange function that stores the selected value:
handleChange: (event, value) => {
this.setState({selectedButtonValue: value});
}
And then push that value to every RadioButtonGroup using the valueSelected property as such;
<RadioButtonGroup name="shipSpeed" defaultSelected="not_light" key={member.uuid}
onChange={this.handleChange}
valueSelected={this.state.selectedButtonValue}
>
I assume you are using "Enhanced Table" from material ui.
If that's the case
replace
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} 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),
);
}
with
if (selectedIndex === -1) {
newSelected = [name];
}
and replace
The Checkbox component with Radio component.
change this
<TableCell padding="checkbox">
<Checkbox
checked={isItemSelected}
inputProps={{ 'aria-labelledby': labelId }}
/>
</TableCell>
to this
<TableCell padding="checkbox">
<Radio
checked={isItemSelected}
inputProps={{ 'aria-labelledby': labelId }}
/>
</TableCell>
You should be able to toggle between the radio buttons as the button only activates when new row is selected and it replaces the old selected state.
I am attaching the implementation of material ui enhanced table with radio button implementation. I did some tweak here and there. You can take a look.
import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { lighten, 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 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 Radio from '#material-ui/core/Radio';
// import IconButton from '#material-ui/core/IconButton';
// import Tooltip from '#material-ui/core/Tooltip';
// import FormControlLabel from '#material-ui/core/FormControlLabel';
// import Switch from '#material-ui/core/Switch';
// import DeleteIcon from '#material-ui/icons/Delete';
// import FilterListIcon from '#material-ui/icons/FilterList';
function createData(name, calories, fat, carbs, protein) {
return { name, calories, fat, carbs, protein };
}
const rows = [
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),
];
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === 'desc'
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
const headCells = [
{ id: 'name', numeric: false, disablePadding: true, label: 'Dessert (100g serving)' },
{ id: 'calories', numeric: true, disablePadding: false, label: 'Calories' },
{ id: 'fat', numeric: true, disablePadding: false, label: 'Fat (g)' },
{ id: 'carbs', numeric: true, disablePadding: false, label: 'Carbs (g)' },
{ id: 'protein', numeric: true, disablePadding: false, label: 'Protein (g)' },
];
function EnhancedTableHead(props) {
const { classes, order, orderBy, onRequestSort } = props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
return (
<TableHead>
<TableRow>
<TableCell padding="checkbox">
</TableCell>
{headCells.map((headCell) => (
<TableCell
key={headCell.id}
align={headCell.numeric ? 'right' : 'left'}
padding={headCell.disablePadding ? 'none' : 'default'}
sortDirection={orderBy === headCell.id ? order : false}
>
<TableSortLabel
active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : 'asc'}
onClick={createSortHandler(headCell.id)}
>
{headCell.label}
{orderBy === headCell.id ? (
<span className={classes.visuallyHidden}>
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
</span>
) : null}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
);
}
EnhancedTableHead.propTypes = {
classes: PropTypes.object.isRequired,
onRequestSort: PropTypes.func.isRequired,
onSelectAllClick: PropTypes.func.isRequired,
order: PropTypes.oneOf(['asc', 'desc']).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired,
};
const useToolbarStyles = makeStyles((theme) => ({
root: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
},
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,
},
title: {
flex: '1 1 100%',
},
}));
const EnhancedTableToolbar = (props) => {
const classes = useToolbarStyles();
const { numSelected } = props;
return (
<Toolbar
className={clsx(classes.root, {
[classes.highlight]: numSelected.length > 0,
})}
>
{numSelected.length > 0 ? (
<Typography className={classes.title} color="inherit" variant="subtitle1" component="div">
{numSelected}
</Typography>
) : (
<Typography className={classes.title} variant="h6" id="tableTitle" component="div">
Nutrition
</Typography>
)}
{/* {numSelected.length > 0 ? (
<Tooltip title="Delete">
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</Tooltip>
) : (
<Tooltip title="Filter list">
<IconButton aria-label="filter list">
<FilterListIcon />
</IconButton>
</Tooltip>
)} */}
</Toolbar>
);
};
EnhancedTableToolbar.propTypes = {
numSelected: PropTypes.string.isRequired,
};
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
paper: {
width: '100%',
marginBottom: theme.spacing(2),
},
table: {
minWidth: 750,
},
visuallyHidden: {
border: 0,
clip: 'rect(0 0 0 0)',
height: 1,
margin: -1,
overflow: 'hidden',
padding: 0,
position: 'absolute',
top: 20,
width: 1,
},
}));
export default function EnhancedTableWithRadio() {
const classes = useStyles();
const [order, setOrder] = React.useState('asc');
const [orderBy, setOrderBy] = React.useState('calories');
const [selected, setSelected] = React.useState('');
const [page, setPage] = React.useState(0);
// const [dense, setDense] = React.useState(false);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === 'asc';
setOrder(isAsc ? 'desc' : 'asc');
setOrderBy(property);
};
const handleClick = (event, name) => {
let newSelected = selected;
if (name !== selected) {
newSelected = name;
}
setSelected(newSelected);
};
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
// const handleChangeDense = (event) => {
// setDense(event.target.checked);
// };
const isSelected = (name) => selected.indexOf(name) !== -1;
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<EnhancedTableToolbar numSelected={selected} />
<TableContainer>
<Table
className={classes.table}
aria-labelledby="tableTitle"
// size={dense ? 'small' : 'medium'}
size = "medium"
aria-label="enhanced table"
>
<EnhancedTableHead
classes={classes}
order={order}
orderBy={orderBy}
onRequestSort={handleRequestSort}
rowCount={rows.length}
/>
<TableBody>
{stableSort(rows, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row, index) => {
const isItemSelected = isSelected(row.name);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover
onClick={(event) => handleClick(event, row.name)}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row.name}
selected={isItemSelected}
>
<TableCell padding="checkbox">
<Radio
checked={isItemSelected}
inputProps={{ 'aria-labelledby': labelId }}
/>
</TableCell>
<TableCell component="th" id={labelId} scope="row" padding="none">
{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>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
{/* <TableRow style={{ height: (dense ? 33 : 53) * emptyRows }}> */}
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
{/* <FormControlLabel
control={<Switch checked={dense} onChange={handleChangeDense} />}
label="Dense padding"
/> */}
</div>
);
}
I had the same problem using a Radio button component inside a cell from a Table, both components from MaterialUi. I resolve like this:
This is my handleChange function to select de value of the Row.id that i use for my app
handleChange(field, event) {
this.setState({[field] : event.target.value});
}
And in my Table component i just use the "Radio" component without a "RadioButtonGoup" component. And use a condition in the "checked" prop of the "Radio" component to show it as checked or not.
<Table aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="center">Selecciona</TableCell>
<TableCell>Brand</TableCell>
<TableCell align="center">Tarjetahabiente</TableCell>
<TableCell align="center">Terminación</TableCell>
<TableCell align="center">Expira</TableCell>
<TableCell align="center">Eliminar</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
<Radio
value={row.id}
defaultSelected={false}
checked={row.id != this.state.paymentSourceId ? false : true}
onChange={this.handleChange.bind(this, 'paymentSourceId')}
/>
</TableCell>
<TableCell align="center">{row.brand}</TableCell>
<TableCell align="center">{row.name}</TableCell>
<TableCell align="center">{row.last4}</TableCell>
<TableCell align="center">{row.exp_month}/{row.exp_year}</TableCell>
<TableCell align="center">
<IconButton
aria-label="delete"
color="primary"
onClick={()=>this.handleDelete(this.state.paymentSourceId)}>
<DeleteIcon />
</IconButton>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>