Material-ui table row onClick bypass for checkbox select

material-ui checkbox checked color
material-table onrowclick
material-ui checkbox onchange not working
material-ui table row height
material-ui table fixed header
material-ui treeview checkbox
material-ui responsive table
tablerowcolumn material-ui

I am using the material-ui data table for sorting. This incorporates a checkbox on each row. I have made it that each row returns a click through to a link.

However, I don't want the checkbox to act as a click though and want it to behave as a checkbox and add the row to selected. But when clicking the checkbox the row link is returned.

I need to exclude that cell from the row link or someway to exclude the checkbox.

https://codesandbox.io/s/rlkv87vor4

This is what I have tried for the logic:

Click handler

if (event.target.classList.contains('selectCheckbox')) {
  return console.log('checkbox select');
  } else {
  return console.log('row link');
}

In my demo row link is always being returned when clicking the checkbox.

<TableCell padding="checkbox">
  <Checkbox className="selectCheckbox" checked={isSelected} />
</TableCell>

The most straightforward way to deal with this is to have two separate handleClick methods for the checkbox and the row (e.g. handleCheckboxClick and handleRowClick).

In handleCheckboxClick you can then call event.stopPropagation(); in order to prevent handleRowClick from being called.

So the following portions of EnhancedTable would change from:

  handleClick = (event, id) => {
    if (event.target.classList.contains("selectCheckbox")) {
      console.log("checkbox select");
    } else {
      console.log("row link");
    }

    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 });
  };
...
<TableRow
  hover
  onClick={event => this.handleClick(event, n.id)}
  role="checkbox"
  aria-checked={isSelected}
  tabIndex={-1}
  key={n.id}
  selected={isSelected}
>
  <TableCell className="selectCheckbox" padding="checkbox">
    <Checkbox
      onClick={event => this.handleClick(event, n.id)}
      className="selectCheckbox"
      checked={isSelected}
    />
  </TableCell>

to something like the following:

  handleCheckboxClick = (event, id) => {
    event.stopPropagation();
    console.log("checkbox select");
    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 });
  };
  handleRowClick = (event, id) => {
    console.log("row link");
  };
...
<TableRow
  hover
  onClick={event => this.handleRowClick(event, n.id)}
  role="checkbox"
  aria-checked={isSelected}
  tabIndex={-1}
  key={n.id}
  selected={isSelected}
>
  <TableCell className="selectCheckbox" padding="checkbox">
    <Checkbox
      onClick={event =>
        this.handleCheckboxClick(event, n.id)
      }
      className="selectCheckbox"
      checked={isSelected}
    />

Here's a CodeSandbox showing this approach:

Material-ui table row onClick bypass for checkbox select, I am using the material-ui data table for sorting. This incorporates a checkbox on each row. I have made it that each row returns a click through  Will automatically set dynamic row height based on the material table element parent (head, body, etc). Component name The MuiTableRow name can be used for providing default props or style overrides at the theme level.

So there are multiple issues here.

1) The className is not a valid property for the Checkbox API https://material-ui.com/api/checkbox/#checkbox-api

2) console.log(event.target) shows that the actual click happens on an svg label used to style the input and not the input itself. So, you cannot directly use inputProps={{className:"selectedCheckbox"}} either and capture the same from the classList

You can refer this sandbox and see how you can get the desired result if you actually click the input : https://codesandbox.io/s/r7j4j638qn

So, a possible answer is to modify the icon property of the Checkbox component and set it to a custom icon with the specified class ? Then it should work as expected.

TableRow API, The API documentation of the TableRow React component. classes, object, Override or extend the styles applied to the component. selected, bool, false, If true , the table row will have the selected shading. Card Content · Card Header · Card Media · Checkbox · Chip · Circular Progress · Click Away Listener · Collapse  Stack Overflow Public questions and answers; Adding an onclick event to a table row. Button onclick event change all the select option selection in a row.

Simply add onClick on the checkbox and call e.stopPropagation(); to prevent call onClick twice from the checkbox and from the row component !

handleClick = (event, id) => {
    event.stopPropagation();

    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});
  };
  <TableRow
                      hover
                      onKeyDown={event => this.handleKeyDown(event, n.id)}
                      role="checkbox"
                      aria-checked={isSelected}
                      tabIndex={-1}
                      key={n.id}
                      onClick={event => onMore(event, n.id)}
                      selected={isSelected}
                    >

                      <TableCell padding="checkbox">
                        <Checkbox color="primary" checked={isSelected}
                                  onClick={event => this.handleClick(event, n.id)}/>
                      </TableCell>
</TableRow>

Checkbox API, The API documentation of the Checkbox React component. classes, object, Override or extend the styles applied to the component. MuiCheckbox-root, Styles applied to the root element. checked .Mui-checked, Pseudo-class Table Cell · Table Container · Table Footer · Table Head · Table Pagination · Table Row​  When including tools, they should be placed directly above or below the table. Structure. A data table contains a header row at the top that lists column names, followed by rows for data. Checkboxes should accompany each row if the user needs to select or manipulate data.

[HOWTO] When mark checkbox row will be highlighted · Issue #283 , [HOWTO] When mark checkbox row will be highlighted #283 material-table'; import { createMuiTheme } from MuiThemeProvider from '@material-ui/core/​styles/MuiThemeProvider'; const theme Just override MUI Theme like '​Remove All Selected Users (Your action)', icon: 'delete', onClick: (evt, data)  I am trying to find the best table to use with my react apps, and for now, the react-table offers everything I need (pagination, server-side control, filtering, sorting, footer row). This being sa

[TableRow] [Table] [TableBody] onRowClick event doesn't work , It would allow to define props on TableRow that override the internal handlers. I needed ccomb added a commit to ccomb/material-ui that referenced this issue on Feb 26, 2016 [Table] Reapply #3492 with checkbox cell highlight. I have the same problem, onClick and onRowClick event doesn't work. Styles applied to the root element if variant="head" or context.table.head. body.MuiTableCell-body: Styles applied to the root element if variant="body" or context.table.body. footer.MuiTableCell-footer: Styles applied to the root element if variant="footer" or context.table.footer. sizeSmall.MuiTableCell-sizeSmall

mui-datatables, Datatables for React using Material-UI. components, object, Custom components used to render the table customSort, function, Override default sorting with custom function. selectableRowsHeader, boolean, true, Show/hide the select all/deselect all checkbox header for selectable rows. Name Type Default Description; autoWidth: bool: false: If true, the width of the popover will automatically be set according to the items inside the menu, otherwise it will be at least the width of the select input.

Comments
  • @MalikBrahimi I recommend that you create your own separate question that demonstrates how to reproduce your problem.
  • I figured out my problem. I was using onChange instead of onClick. Do you know what the nuance is between them for a checkbox?
  • @MalikBrahimi The row is responding to the click event. The row doesn't have an onChange event, so stopping propagation of the onChange event for the Checkbox will have no effect on whether the click event propagates to the row.
  • @MalikBrahimi As far as the difference between the events for checkboxes, this is addressed elsewhere (e.g. stackoverflow.com/questions/5575338/…).
  • it still returns "row link" and not "checkbox select", so in my case it would take me to another view rather than simply checking the checkbox
  • okay, the title was a bit misleading, I thought you were worried about the click getting bypassed. let me look again
  • className is a valid property for any DOM element and the docs you referenced indicate "Any other properties supplied will be spread to the root element (native element)."
  • I could not find the className at the event target. Could be a bug? Tried the good ol' console.log() @RyanCogswell
  • The className is being applied to the outermost span that wraps the checkbox input. The overall structure created is <span class="selectCheckbox and other classes"><span><svg/><input type="checkbox"/></span></span>.