preserve the form data so when we update the additionalErrors the dat…
…a is not reset to the initial state
Deploy Preview for jsonforms-examples ready!
| Name | Link |
|---|---|
| Latest commit | 22b4016198c895f6c7637bb7fa7abb272dc65796 |
| Latest deploy log | https://app.netlify.com/projects/jsonforms-examples/deploys/69418ccfefa4f50007b1fb9c |
| Deploy Preview | https://deploy-preview-2478--jsonforms-examples.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify project configuration.
@sdirix please review, to check the issue in the current master branch just apply the change for ExampleView.vue and then try to test the additional-errors example, e.g. change the form once it is loaded and then click on the "Add Additonal Error" button and observe that the form data is reset, then check the https://deploy-preview-2478--jsonforms-examples.netlify.app/vue-vuetify/#additional-errors
coverage: 82.798%. remained the same when pulling 4803decb50d01f6322e90353156a3261658a3f77 on kchobantonov:preserve-edit-data into 6bbfbb331df36343b0346d41ed80854456fff9ff on eclipsesource:master.
So the error occurs only if the user of JSON Forms:
- hands over new
additionalErrorsto JSON Forms component - does not hand over an updated state of the the
data
I don't think that this is a valid use case. Either the props of the JSON Forms component are "frozen" and the management is done by JSON Forms, or the props are always live. The error case is a weird mix which is not really valid.
The same issue will occur in Angular and React if only parts of the props are updated. Either they should never be updated by the user, i.e. uncontrolled variant, or they should all be updated, i.e. controlled variant.
I understand the distinction between controlled and uncontrolled usage, but in practice consumers of JSON Forms may mix these patterns—intentionally or unintentionally—especially in larger applications with multiple state sources. From a robustness standpoint, the component should ideally handle all variants, including partial updates.
Even if this “weird mix” is not the recommended pattern, supporting it makes JSON Forms more fault-tolerant and easier to integrate in real-world scenarios where the state flow is not always perfectly aligned with controlled/uncontrolled paradigms.
@sdirix @lucas-koehler please also check the update where the generated schema and uischema are properly regenerated when the data is changes - please check this example dynamic when if you change the data to a number and save then the ui will be updated accordingly - in previous versions that was not true.
@sdirix please review
@sdirix @lucas-koehler please review
Hi @kchobantonov , Thanks for the updates! I have some comments inline unrelated to the setting of
this.dataToUse = newEvent.data;.I am still a bit concerned about this:
It makes the data propagation less intuitive:
- In the controlled case, the data is set to dataToUse again after it has already been updated. Granted, this does not trigger an additional invocation of
coreDataToUpdate().- In the uncontrolled case, this triggers
coreDataToUpdatean additional time without it being needed. This has a possible performance penalty because it invokes the middleware again- In the mixed case, it triggers the
coreDataToUpdatelike in the uncontrolled case. From a data point of view that should also not be necessary because the data is uncontrolled. Granted, this is acceptable considering the issues that this tries to fix.As this does make the state handling less intuitive and lowers performance in uncontrolled mode as far as I can tell, I am leaning towards not introducing supporting this mixed case.
Do you have a concrete use case in mind where this is necessary? For a diffuse robustness increase, I prefer to not introduce this because consumers can always control the data in the component rendering the form. Even if the state handling is more complex for other properties. We can of course add this to the documentation though.
Yes I have a specific case in my camunda-jsonforms-plugin project where when the form is submitted then if the backend determines that some of the fields is not valid because of some runtime constraints then I'm returning back to the UI additionalErrors so those can be rendered on the UI to represent the server side validated fields but when I set the additionalErrors that triggers the setting of the forms data and etc. which defacto reverts my changed data to whatever I had on the first load which is definitely not what I wanted since that will not display the data in the form as it was before submitting that. It is given that I can by pass that (in the example project even I do capture the data and preserve that) but since that looks like a bug to me to be honest I wanted to see that in the core itself instead of me handling that in multiple places like the vuetify3 demo app in the jsonforms project, in my camunda-jsonforms-plugin in the jsonforms-vuetify-webcomponent project and so on.
@lucas-koehler thanks for the review - please check my comments
I think we just have a clash of expectations here.
@kchobantonov is treating data like a defaultValue in React. Handing over an initial value and never expected to update it. We, the JSON Forms team, treat data like a controlled prop which needs to be updated.
This is additionally complicated by the fact that data is optional. The user could expect that if they never handed in data and only update the additionalErrors, that they still do not need to update their data. But this is not the case currently.
I think it would be good to clearly differentiate the two behaviors and therefore expectations. For this we can introduce two new props, modelValue which is the usual name in Vue 3 with v-model support, and defaultValue for the "hand over once and never update" case. Accordingly we will then behave within the JSON Forms component. We keep data as it is currently for backward compatibility, i.e. treat it the same way as modelValue.
Alternatively we could also not create a new modelValue prop but just offer an update:data event for custom v-model:data support. In fact that's even better to avoid introducing a redundant variable.
Does this make sense for everybody? @lucas-koehler What do you think? @kchobantonov would you be willing to implement this?
@sdirix Thanks for the explanation. I agree with your sentiment. Both suggested solutions are fine with me but I prefer the second one to keep the API of the JSON Forms component concise. I.e.:
Alternatively we could also not create a new modelValue prop but just offer an update:data event for custom v-model:data support. In fact that's even better to avoid introducing a redundant variable.
Yes, I also don’t think we need to introduce new props—or events, for that matter.
The example I outlined can indeed be interpreted as using the value only as an initial input for the form, without updating it from the outside afterward. However, that does not cover the full range of use cases. In my case, there are scenarios where the form data is modified as a result of external actions, typically triggered by clicking a button, and those updates need to be reflected in the form.
The issues I’m facing with the current implementation are the following:
-
Updating additionalErrors causes a full internal update with the previously set data (overriding the data that was updated meanwhile) When I update additionalErrors, I do not expect this to trigger that behaviour. In particular, the data currently entered in the form should be preserved. I do have a workaround that avoids changing the JsonForms component itself, but that solution would require duplicating the same logic across multiple projects that I have. Conceptually, I don’t think that changing a property which is not directly related to the data should result in the data being reset.
-
Schema and UI model are not recomputed when data changes externally That issue is harder to work around.. For example, if only the data is provided, the JSON Schema is computed from it, and then the UI model is computed from the schema. When the data is updated externally, I would therefore expect the computed schema and UI model to be updated as well, since the underlying data has changed. However, this recomputation does not happen when the data is updated from the outside, which leads to inconsistencies.
-
there is an issue with the schema generator that does not produce the expected result in all cases and hence it was also changed. - again can't fix that as a workaround.
Yes, I also don’t think we need to introduce new props—or events, for that matter.
The example I outlined can indeed be interpreted as using the value only as an initial input for the form, without updating it from the outside afterward. However, that does not cover the full range of use cases. In my case, there are scenarios where the form data is modified as a result of external actions, typically triggered by clicking a button, and those updates need to be reflected in the form.
The issues I’m facing with the current implementation are the following:
- Updating additionalErrors causes a full internal update with the previously set data (overriding the data that was updated meanwhile) When I update additionalErrors, I do not expect this to trigger that behaviour. In particular, the data currently entered in the form should be preserved. I do have a workaround that avoids changing the JsonForms component itself, but that solution would require duplicating the same logic across multiple projects that I have. Conceptually, I don’t think that changing a property which is not directly related to the data should result in the data being reset.
This is the case we mostly discussed here in the PR. So when you have the use case that you update data externally, you would use v-model:data and then it's always up to date. Changing additionalErrors additionally should work without an issue then.
- Schema and UI model are not recomputed when data changes externally That issue is harder to work around.. For example, if only the data is provided, the JSON Schema is computed from it, and then the UI model is computed from the schema. When the data is updated externally, I would therefore expect the computed schema and UI model to be updated as well, since the underlying data has changed. However, this recomputation does not happen when the data is updated from the outside, which leads to inconsistencies.
- there is an issue with the schema generator that does not produce the expected result in all cases and hence it was also changed. - again can't fix that as a workaround.
Yes these two use cases make sense to me, NOT storing schema and UI Schema in the component (or storing and comparing to not always update the instance with no actual content changes) but regenerating them when new data is retrieved makes sense to me on a high level without looking into the details yet.