Dynamically Update Form Data in Array Based on Checkbox Selection

I built a custom Array Layout renderer in React and am having some issues getting the data to update properly.

Requirement:
This particular part of the form allows users to add address information, as many as they want. Each address object they add has a checkbox that allows them to specify if an address is their “preferred” address. If that checkbox is checked, I need to make sure that all others in the array are unchecked (set to false).

I figured I could pass the form data in to the renderer via React context, as I’ve seen mentioned in other threads, and modify as needed. I followed your emitter example from this post (Customize onChange Method - #2 by sdirix) and while it all works in so far as I was able to hook into the onChange event for the checkbox and I can access the data stored in context in my custom HOC, I’m not clear on what to do next.

JsonForms handles updating the data object on its own and I cannot figure out how to override those values with the data I’m changing.

Custom onChange Handler:

import { Component, useContext } from "react";
import { ApplicationContext } from "../context/ApplicationContext";

const withCustomHandleChangeEmitter = (Component: any) => {
  return (props: any) => {
    // consume your context which you set up outside of JSON Forms
    const myContextInstance = useContext(ApplicationContext);
    const myEmitter = myContextInstance.setFormData;

    // create a new handleChange method which first does the regular update and then tells the emitter which data changed
    const handleChangeAndEmit = (path: string, updater: any) => {
      props.handleChange(path, updater);

      const pathSplit = path.split('.').filter(Boolean);
      const formDataParsed = JSON.parse(myContextInstance.formData);

      const updatedAddresses = formDataParsed.addresses.map((address: any, index: number) => {
          if (index === Number(pathSplit[1])) {
              return { ...address, preferred: updater };
          } else {
              return { ...address, preferred: false };
          }
      });

      console.log('updater', updater);
      console.log('myContextInstance.formData', {
        ...formDataParsed,
        addresses: updatedAddresses
        });

      myEmitter({
        ...formDataParsed,
        addresses: updatedAddresses
        });
    }

    // pass down all props as they are but overwrite handleChange
    return <Component {...props} handleChange={handleChangeAndEmit} />
  }
}

export default withCustomHandleChangeEmitter;

Any help would be appreciated!

Hi @RTyska ,

as I understand your requirement, you want to immediately edit your data when a “preferred” checkbox is selected. Instead of adding this HOC, you can also have a look at the new middleware support.
This should allow you to directly update your data together with the “preferred” checkbox selection.

If you want to stick to the emitter approach, you should be able to update the data by also using the handleChange method. In your case with the addresses, its first parameter path needs to point to the array containing the addresses and the updater applies your change.

Hope that helps and best regards,
Lucas

Hey Lucas,

I did actually get it working with the HOC, but the middleware is intriguing. I’ll take a look.

Thanks!
Robert