score:22

Accepted answer

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:

Edit Material demo

score:1

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.

score:2

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>

Related Query

More Query from same tag