最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Adding a Radio button of material UI inside row cell in table, - Stack Overflow

programmeradmin13浏览0评论

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> ponent, 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.

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> ponent, 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.

Share Improve this question asked Aug 29, 2017 at 14:52 Nitish PhanseNitish Phanse 5621 gold badge9 silver badges17 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

You'll probably, unfortunately, need to manage the state of your radio buttons manually, as a controlled ponent.

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 ponent with Radio ponent.

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('Honeyb', 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, parator) {
  const stabilizedThis = array.map((el, index) => [el, index]);
  stabilizedThis.sort((a, b) => {
    const order = parator(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" ponent="div">
          {numSelected}
        </Typography>
      ) : (
        <Typography className={classes.title} variant="h6" id="tableTitle" ponent="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 ponent="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]}
          ponent="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 ponent inside a cell from a Table, both ponents 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 ponent i just use the "Radio" ponent without a "RadioButtonGoup" ponent. And use a condition in the "checked" prop of the "Radio" ponent 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 ponent="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>

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论