Computed field values

I’ve been using the standalone version of JsonForms in a project that has countless forms and it has made life so much easier, thank you very much for your work on it.

There are a series of forms that I’m currently working on that need to compute field values based on the values of other fields. So for example the form has fields 1, 2 and 3. If the user enters values for 1 and 2, field 3 needs to be automatically calculated. If they enter values for 2 and 3, field 1 will be calculated.

Do you have any suggestions on how I might achieve that with JsonForms? Modifying the data object and feeding it back to the JasonForms component doesn’t appear to be an option. Computing values seems like it would be a relatively common situation, so I’m hoping that there’s a hook in there somewhere that could be used to achieve it.

[original thread by user4060]

Hi @user4060(user4060), thanks, we appreciate it :wink:

Modifying the data object and feeding it back to the JasonForms component doesn’t appear to be an option.

This approach would work. However it isn’t the cleanest one as the intermediate state will also be rendered (e.g. 1 and 2 are set but 3 is not yet calculated).

Currently the easiest way is to register custom renderers for all relevant fields. These can just hand over their props to the existing controls of JSON Forms, so they are easy to implement. The only parameter you need to modify is the handleChange method. Here you would not only change their own data, but also all other affected fields.

  • To access the whole form data and the general dispatch you can use useJsonForms which returns the whole “store”

  • Depending on your use cases you could also modify enabled or render calculated input values with a different background etc.

  • If you have this use case multiple times you could also generalize this behavior and make it declaratively configurable by adding respective custom options to your ui schema.

Instead of using custom renderers or modifying the data outside of JSON Forms you could also use a middleware approach. By placing the middleware between our coreReducer and the maintained state you could check for data changes and modify the data to your liking. Compared with the first approach (modifying the data outside of JSON Forms) this is much cleaner as there is never any intermediate “dirty” state and you don’t need any custom renderer. The downside is that we currently don’t support this out of the box, see #1670. To do this with the current codebase you need to copy the JsonFormsStateProvider and modify it directly.

So for now I would like to suggest using the custom renderer approach.

[user4060]

Thanks so much for the detailed answer Stefan. Custom renderers with ui schema options could definitely work, I’ll give it a try.

Adding a middleware concept to JsonForms as you describe in #1670 would be a really powerful enhancement, I can see many situations where it would be useful.

[maulik-modi]

@user4060(user4060) , I am also in the same boat right now, wanted to know if Custom renderer worked for you?

[user4060]

Hi Maulik,

I did a test with custom renderers and it worked, it’s certainly a viable option.

In our case though, there are many small, low value forms and a requirement to be able to add more in the future with little effort. It meant that custom renderers were too cumbersome. I ended up simply passing the the changed data back to JsonForms instead. Not an ideal solution, but since our forms are very small the extra renders aren’t an issue.

Hi @user4060(user4060), couldn’t you register the custom renderer in a generic way so that it works for all forms? I guess there must be some way to detect dependent fields as you probably also implemented the data manipulation in a generic way?

[maulik-modi]

@sdirix(sdirix) , Do you mean adding custom properties in data schema e.g.

[maulik-modi]

country has “state” as dependent fields?

Yes for example by marking them in JSON Schema or in the UI Schema. Alternatively when the naming scheme of them is always the same this is an implicit marking, so you could register your custom controls for them.

[user4060]

I’m sure I probably could have, but there wasn’t an immediately obvious answer on how. In our case each form has custom logic for calculating the value and also custom logic for deciding when/if to calculate a value. They aren’t all limited to three fields and requiring user input in two.

Since passing the value through to JSONForms a second time seems to work fine and not slow the app down excessively, it seemed like the most expedient option. I see that you’ve added the middleware concept to the next milestone, if it makes it into a release I’ll definitely move the logic over to utilise that in the future.

[maulik-modi]

@sdirix(sdirix) and @user4060(user4060) , perhaps this example can be converted to reflect current API and hooks would be immensely helpful. Populate input field using api call · Issue #987 · eclipsesource/jsonforms · GitHub