onChange gets called on init

Can the “JsonForms” object be configured in some way to not call “onChange” on the initial data set? Only when a form event or data change has occured?

const onChange = ({ errors, data }) =>
{
// Gets called on initial “data” set
// Can it only be called on an input event (text field changed, checkbox checked, etc)?
}

return (
<JsonForms
{…schemas}
data={data}
renderers={materialRenderers}
cells={materialCells}
onChange={onChange}
/>
);

Cheers.

[original thread by JasonMichaelSmith]

At the moment: No. JSON Forms will emit the onChange immediately because:

  • Ajv could be configured to add additional data which the user needs to be informed about

  • The event also emits the initial validation results

We could think about making this configurable. Can you tell more about your use case and why the current behavior is not desireable?

[JasonMichaelSmith]

Thanks for the quick reply,

I essentially have a “Submit” button I wanted to keep greyed-out (disabled) until some updates have occured that differ from the initial data values assigned.

It’s a bit like a CMS, where pre-filled data in the form represents the last iteration of the content the user submitted, so it’s technically already passed form validation from a prior submit, so there’s no errors I could query to disable submission right off the bat.

I also have multiple JsonForm instances for data archetypes, with one “Submit” button for them all, so the logic “if user has changed anything enable submit” has to be fairly abstract, not specific to a single set of JSON data.

Basic idea with a single form:

[JasonMichaelSmith]

const JsonForm = ({ data, schemas, onChange }) =>
{
const [canUpdate, setCanUpdate] = useState(false);
const [dataUpdates, setDataUpdates] = useState(null);

const onChange = ({ errors, data }) =>
{
    setDataUpdates(data);
    !canUpdate && setCanUpdate(true);
};

const onSubmit = () =>
{
    setCanUpdate(false);
    submit(dataUpdates, success => {}, error => setCanUpdate(true));
};

return (
    <>
        <Button variant="contained" onClick={onSubmit} color="secondary" disabled={!canUpdate}>Submit</Button>
        <JsonForms
            {...schemas}
            data={data}
            renderers={materialRenderers}
            cells={materialCells}
            onChange={onChange}
        />
    </>
);

};

Technically you could write some logic which just dismisses the first event coming from JSON Forms or checks whether the data instance emitted by JSON Forms is the initial data handed in.

However I would think about the UX experience. Why force the user to change the form before they can click submit? What if they just enter a space somewhere (and maybe even delete it again) and then click submit?

If you need them to enter specific data you can model this via JSON Schema validation and just disable the submit button as long as there are validation errors.

[JasonMichaelSmith]

Thanks Stefan,

I assumed the simplest approach would be to simply ignore the first onChange call, or do an equal check on the onChange data and the init data.

UX wise, it’s like when some apps have the “Save” button greyed-out to signify to the user that there’s definitely no changes pending they need to submit. Not a huge issue of course if it’s always enabled, but might save a few submit API calls to our servers if we’re being pedantic.

Hi @jasonmichaelsmith(jasonmichaelsmith), I see that makes sense. For now I would go with the instance check (i.e. ===).

I’ll keep the use case in mind to offer a way for the user to detect a “real” change, for example we could mark the initial event in a special way (e.g. initial: true).

Also we’re thinking about introducing an optional middleware entry point so users could hook into core JSON Forms functionality. In that case detecting a real change would be straightforward.