-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New validation extension #369
Comments
Just to make sure, they would also trigger on a normal/full validate call, right? Or are we talking about the 'task validation' concept?
And, to make it very clear, these validations should be returned from the save operation, for example in a new
|
Yes, they would be triggered on normal/full validation. I think we should make a even more clear separation between task and data validation.
Yes, I think that is the logical place to return them, removing the need to do an extra validation call after the data is saved. But I think we should still implement the validation endpoint there for the users consuming an application only through the API.
Yep:
|
Great! And sorry - i missed that last point! |
We should also keep in mind that simple validations like "field should not be empty" can easily be implemented using expression based validation: #311 as these validations can be executed by the frontend during formfilling and then again by the backend when data is submitted. |
Quick question regarding |
One more thing, in v4, we store all validations even though they are not visible. This extends to validations for hidden components as well, so we don't need to "trigger" running validations whenever a component is unhidden. This means that the backend should no longer remove hidden data before running validations. We may need to add a featureflag so that it still works the same with v3. |
Pretty sure this is a bad idea. This will make it hard to have correct dependent validation on hidden fields (ie. the error shows up on an always visible feld but depends on a field that sometimes is hidden. Showing fields will only trigger on a field change anyway, so frontend should just report the newly shown fields as changed. |
How would the backend know which fields to validate if the data has not actually changed? From a frontend perspective, the data is always there, regardless of its hidden status. So when saving it would not recognize a component becoming unhidden as fields being added to the data model. But I suppose if the backend does the diff and removes hidden data on the old and new formData it would see it that way. |
I'm aware that developers have re-used the code to remove hidden data when running validations, and I've seen bugs being introduced because the validation logic was too simple and ignored potential hidden fields. As an example, let's say you have the classic form:
And the validation logic is:
The result here is that if you type an invalid phone number, change your mind and switch to show the email field, the validation for an invalid phone number would still remain. So, I think there are multiple strategies to solve this today:
But I think those two strategies have a crucial weakness; they require that the application developer fixes the problem for us. That's why I don't like them, and I think we need to do better.
Not sure what the use-case is for this, or if you have a good example for it, @ivarne, but I struggle to understand what's the desired outcome there. Do we want to remove the validation message for the always visible field when the source field is hidden? Or do we want the validation to stay as long as the data stays? As long as I don't have a good grasp on that use-case, I would think it depends - and that, of course, is awful. We don't want to make this configurable.
Technically, expressions can also be used to hide/unhide fields on language changes - but I hope nobody is using that. We don't necessarily save the form data (and especially don't run validation again) when the language changes. In the near future, when we'll support sub forms and multiple data models per process step, it will be very easy (and I guess, even recommended) to store prefill/shadow fields/metadata in a separate data model, and use that data model for expressions. So, if you'd like to go down that route of hiding/removing validation messages when they are hidden, it will quickly become a bottleneck when you have to fetch all kinds of different data models to evaluate expressions in order to figure it out. We still only call the request to save data (and validate) per data model. And again, technically, we still need to support the old hide/unhide logic in frontend, and there you can even hide a field based on the positions of the sun and the moon - or the time of day, or some random number - but yes, it would only be possible to trigger it via a change in some data model. |
I want the app developer to always see the real data that they intend to validate (and not see potential extra data that is hidden and will be removed). The natural result that follows from that, is that for validation purposes there are two changes when you toggle the
Hard to find concrete examples where there isn't really a better way to handle validation, but one somewhat contrived issue is that you at the end you declare that all contacts live in Norway, and you can add a validation error if you use a foreign country code in the phone number.
No. Neither Frontend, nor backend knows the list of data model keys used to create a validation issue (with the current design). We only know the What I want is for the validation implementation to know that the phone number must be revalidated when you click on the contact method radio button. One issue that appears is what to do with validation issues pointing to a hidden field. I think that should be flagged as an problem in dev tools, but otherwise ignored until form submission where it is shown as a task issue that prevents processing of
My initial thought was that frontend would need to also report fields that changed from Backend could possibly use the diff dictionary from frontend about the real data model changes, and recreate both the previous and new models, remove hidden data from both and create a new diff for validation. Writing this out indicates that it could work, but adds some load to the server that could be reduced if frontend does the work and provides the combined list of changed fields. Another drawback with this issue is that expressions might reference other data models and increase the time required to save/partially validate, and frontend has this info in memory anyway. |
Looks like we're coming to the same conclusion here.. 😅 I ended up talking with @RonnyB71 and @tjololo about this as well, spontaneously after a meeting we just had. This takes me back a bit. I remember a discussion about what to do with form data for hidden components in april 2022, right after I had started working here - might also be the day we first met, @ivarne. Not sure if you remember it, but I believe the consensus then was that frontend should simply store all data server-side, regardless of the data being accessible in the form. The reason, of course, is that quickly changing between a radio (like the phone/email described above) should not make you lose your data (i.e. the phone number you started typing). I remember thinking back then that it seemed like an incredibly complex way of solving a seemingly minor problem. In my mind, a user probably won't expect that (hidden) phone number to re-appear in the form for very long, and especially not after a refresh (or even after continuing to work on the same instance on another device). Storing that stale (and sometimes schema-breaking) data client-side seems like a better solution. I think there's a potential privacy issue in storing hidden data and potentially submitting it to the service owner as well. Ideally I would like for the client-side to be the one to clean away hidden data - and, as I believe you've indicated as well, send the form data with hidden fields removed to the backend. In that world, there would be little need for removing hidden fields on the backend, apart of course from shadow fields. I think it's unrealistic that API clients would send in data not needed, so I don't think the cleaning pass is needed there at all. Such a solution would solve a lot. There's no need for the application developer to implement any of my suggested workarounds from above, the backend gets a cleaner data model, and I think it's a small win for privacy. I first thought it would be nice to store the data in Even if we end up deprecating the hidden data removal stuff on the backend, expression support is alive and kicking, especially now because of the expression-based validation functionality. EDIT: What I didn't think of when writing this is that we still need to evaluate |
Key management for encryption is very easy, as the key can just be stored on the instance with the same access restrictions as the form content. If you persist the full data model encrypted in the client and always send content with hidden data removal, that will definitely help simplify the backend without adding total complexity. The storage is required for offline capability anyway. |
Description
Backend issue for EPIC Altinn/app-template-dotnet#180
Today custom validations performed in the backend is done by implementing the
IInstanceValidator
interface.The code is triggered by frontend either just before the process/next call is performed or if singelfield validation is configured.
The same code is executed for both singel and full validation and is a place for mistakes and unclear logic.
Another problem is that if a previously error is fixed the code needs to generate a
"FIXED"
validation issue so that frontend can remove it.The new implementation should support that one group of validations should be triggered if a field is changed, but all validation logic should be triggered when the process is tried to be moved to the next step.
The response from a group of validations should be the same either if it's ran as a singelfield validation or a full validation and the data is the same.
List of wanted functionality, this is a work in progress:
Altinn.App.Core.Models.Validation.ValidationIssue
should be extended withValidationUrgency
to give the developer a way to define when the issue should be shown.Additional Information
Example of a repsone from a controller where one validation implementation is triggered:
Full validation with issues from multiple validation groups:
The text was updated successfully, but these errors were encountered: