Home > database >  Add multiple values from checkbox to array of objects
Add multiple values from checkbox to array of objects

Time:10-01

I have some checkboxes on each object, and I would like to save the values.

Array of objects

[

    {
      "title": "Kevin Joe",
      "id": "365DmXom2V13xOqagTHczU",
      "enabledUnits": ""
    },
    {
      "title": "Kevin 2",
      "id": "365DmXom2V13xOqagTHczU",
      "enabledUnits": ""
    }

]

Some dummy units

  const dummyUnits = ["Unit 1", "Unit 2", "Unit 3", "Unit 4", "Unit 5"]

mockup

If I click on Unit 1 and Unit 2 For 'Kevin Joe'. This would be the desired result. Added to the object.

[

    {
      "title": "Kevin Joe",
      "id": "365DmXom2V13xOqagTHczU",
      "enabledUnits": "Unit 1, Unit 2"
    },
    {
      "title": "Kevin 2",
      "id": "365DmXom2V13xOqagTHczU",
      "enabledUnits": ""
    }

]

Current onChange handler, Is working but is just adding the single value, not multiple.

  const createOnChangeHandlerUnits = (floorPlan: FloorPlan, property: 'enabledUnits') => (
    e: React.ChangeEvent<HTMLInputElement>
) => {
    const {value} = e.target;

    setFloorPlans(floorPlans => {
        return floorPlans.map(entry => {

            if (entry.id === floorPlan.id) {
                return {...entry, [property]: value};
            }
            return entry;

        });
    });
    props.sdk.field.setValue(floorPlans);
};
{dummyUnits.map((unit, i) => {
   return (
      <CheckboxField id={unit} data-id={i} key={i} value={unit} onChange{(createOnChangeHandlerUnits(floorPlan, 'enabledUnits'))} labelText={unit} />)
})}

CodePudding user response:

Use string concatenation as follows.

    setFloorPlans(floorPlans => {
        return floorPlans.map(entry => {

            if (entry.id === floorPlan.id) {
                return {...entry, [property]: entry[property].concat(`,${value}`)};
            }
            return entry;

        });
    });

CodePudding user response:

To toggle a value, you have to check if it's already in the string

if (entry.id === floorPlan.id && !entry[property].includes(value))

If it's not, I'd create an array using split and push the value inside, then join the values

entry[property].split(',').push(value).join(',')

If it is, you have to filter through the items to remove the toggled item, then join the values

entry[property].split(',').filter(item => item !== value).join(',')

The whole code

if (entry.id === floorPlan.id && !entry[property].includes(value)) {
  return { ...entry, [property]: entry[property].split(',').push(value).join(',') };
} else if (entry.id === floorPlan.id) {
  return {
    ...entry, 
    [property]: entry[property]
      .split(',')
      .filter(item => item !== value)
      .join(',') };
  }
}

return entry;

Although I don't think that's a good approach. I'd use an array as the type of enabledUnits for one. Maybe create a boolean variable to contain the toggled state. This seems a little overkill to me and also expensive to mutate the data all the time.


Edit

const setChecked = (
  floorPlan: FloorPlan,
  property: 'enabledUnits'
) => (e: React.ChangeEvent<HTMLInputElement>) => {
  const {value} = e.target;

  const item = floorPlans.find(entry => entry.id === floorPlan.id);
  return item[property].includes(value);
};
  • Related