tom harrison
tom harrison

Reputation: 3433

enabled/disable checkbox based on object property in array

I am generating an array of objects and then Outputting these into a list, each objects has a checkbox that then adds it to the changeableElements array if it is checked

I am having trouble getting it to show only objects that are added to the array to appear as checked, and also disabled all of the other checkboxes once 3 are selected, how can I do this?

             const [items, setItems] = useState(
               [...Array(301)].map(
                    (_, i) => ({ name: `element ${i}`, selected: false, id: `element_uid_${i}}` }),
                 ),
                   )
             const [changeableElements, setchangeableElements] = useState([])
             const updatechangeableElements = (item) => {
              setchangeableElements(changeableElements.concat(item))
             }

                    <ElementsListWrap>
          {items.slice(0, itemsLimit !== null ? itemsLimit : Infinity)
          .filter((item) => new RegExp(`^${searchValue.toLowerCase()}`).test(item.name))
          .map((item) => (
            <div
              key={item.name}
            >
              {console.log('bkakask',changeableElements.filter((i) => item.id === i.id))}
              <ElementWrap>
                <Checkbox
                  key={item.name}
                  onChange={() => updatechangeableElements({ ...item, selected: true })}
                  type="checkbox"
                  checked={changeableElements.filter(i => item.id === i.selected === true).length > 0}
                  disabled={items.filter((i) => i.selected).length > 2 && item.selected !== true}
                />
                {console.log(changeableElements.map(bla => item.id === bla.id))}
                {item.name}
              </ElementWrap>
            </div>
            ),
          )}
        </ElementsListWrap>

Upvotes: 0

Views: 554

Answers (2)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196142

You are setting checked to the result of filter which will always be an array (sometimes empty), so always truthy.

You likely need to use something like this

    <Checkbox
       key={item.name}
       onChange={() => updatechangeableElements({ ...item, selected: true })}
       type="checkbox"
       checked={changeableElements.find(i => item.id === i && item.selected === true)}
       disabled={items.filter((i) => i.selected).length > 2 && item.selected !== true}
    />

update

This should handle both checked and disabled states.

.map((item) => {
    const isChecked = item.selected && changeableElements.some(i => item.id === i);
    const isDisabled = !isChecked && (items.filter((i) => i.selected).length > 2);
    return (
      <div
        key={item.name}
      >
        <ElementWrap>
          <Checkbox
            key={item.name}
            onChange={() => updatechangeableElements({ ...item, selected: true })}
            type="checkbox"
            checked={isChecked}
            disabled={isDisabled}
          />
          {item.name}
        </ElementWrap>
      </div>
      )},

Upvotes: 1

GoldenaArcher
GoldenaArcher

Reputation: 983

filter() does not return boolean, and checkbox is checked if checked property is true.

So you might want change the checked section to:

checked={changeableElements.filter(item => item.id === item.selected === true).length > 0}

Instead of:

checked={changeableElements.filter(item => item.id === item.selected === true)}

For disable issue, have you map the items? Or you only render each object in the array? If you only render one item in the array, the condition will never be met.

Upvotes: 0

Related Questions