D555
D555

Reputation: 1832

Unable to check the checkboxes in loop in Material UI

I am using Material-UI and React Hooks. I am running a loop in which I am printing the checkboxes. I am unable to check or uncheck them. They seem to be readonly. Nothing happens when I click on them. I console logged to see and the hooks are working fine and selectedExpertArr state is getting updated properly but the checkboxes are not getting checked.

The code is like:

const [selectedExpertArr, setSelectedExpertArr] = useState([]);

The handler function is as follows:

const handleSelectedExperts = (e) => {
    console.log('selectedExpertArr')
    let clonedExpertArr = [...selectedExpertArr];
    if(e.target.checked === true) {
      clonedExpertArr.push(e.target.value)
      setSelectedExpertArr(clonedExpertArr);
    } else {
      let filtered = selectedExpertArr.filter((expert) => {
          return expert !== e.target.value;
      });

      clonedExpertArr = filtered;
      setSelectedExpertArr(clonedExpertArr);
    }

  }

The loop code is as follows:

         <DialogContent>
                <List>
                    {expertNames.map(expert => (
                    <ListItem button key={expert.id}>
                        <Checkbox
                            checked={(selectedExpertArr.indexOf(expert.id) > -1)? true : false }
                            name="expertCheckbox"
                            onChange={handleSelectedExperts}
                            value={expert.id}
                            color="primary"
                            inputProps={{ 'aria-label': 'expert checkbox' }}
                        />
                        <ListItemText primary={expert.username} />
                    </ListItem>
                    ))}
                </List>
        </DialogContent>

Upvotes: 1

Views: 1282

Answers (3)

Junius L
Junius L

Reputation: 16122

It's because clonedExpertArr.push(e.target.value) saves the value as a string and you are comparing a number here

 checked={(selectedExpertArr.indexOf(expert.id) > -1)? true : false }

Upvotes: 1

Muhammad Danial Iqbal
Muhammad Danial Iqbal

Reputation: 1776

I guess the issue is with fetching value from target in the hook. Pass that in the loop using arrow function like

  <DialogContent>
            <List>
                {expertNames.map(expert => (
                <ListItem button key={expert.id}>
                    <Checkbox
                        checked={(selectedExpertArr.indexOf(expert.id) > -1)? true : false }
                        name="expertCheckbox"
                        onChange={(e)=> {handleSelectedExperts(e, expert.id)}}
                        value={expert.id}
                        color="primary"
                        inputProps={{ 'aria-label': 'expert checkbox' }}
                    />
                    <ListItemText primary={expert.username} />
                </ListItem>
                ))}
            </List>
    </DialogContent>

Then modify your hook like pasted below:

const handleSelectedExperts = (e, value) => {
    console.log('selectedExpertArr')
    let clonedExpertArr = [...selectedExpertArr];
    if(e.target.checked) {
      clonedExpertArr.push(value)
      setSelectedExpertArr(clonedExpertArr);
    } else {
      let filtered = selectedExpertArr.filter((expert) => {
          return expert !== value;
      });
      clonedExpertArr = filtered;
      setSelectedExpertArr(clonedExpertArr);
    }
  }

Hope that works for you :)

Upvotes: 0

Fyodor Yemelyanenko
Fyodor Yemelyanenko

Reputation: 11848

The e.target.value is of type string, but seems, that expert.id is number. So you are adding to clonedExpertArr strings but search for number (selectedExpertArr.indexOf(expert.id) > -1)

To correct, convert e.target.value to number with +e.target.value

The corrected code will be

const handleSelectedExperts = (e) => {
    console.log('selectedExpertArr')
    let clonedExpertArr = [...selectedExpertArr];
    if(e.target.checked === true) {
      clonedExpertArr.push(+e.target.value)
      setSelectedExpertArr(clonedExpertArr);
    } else {
      let filtered = selectedExpertArr.filter((expert) => {
          return expert !== +e.target.value;
      });

      clonedExpertArr = filtered;
      setSelectedExpertArr(clonedExpertArr);
    }

  }

Working demo

Upvotes: 1

Related Questions