-
Notifications
You must be signed in to change notification settings - Fork 8
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
Validation - Future direction and principles #180
Comments
I was about to write a new issue, when I found this one. Adding my thoughts here. I don't think we're quite done yet finding a solution that fits all use-cases we want to cover. BackgroundCurrently, validation is somewhat modeled on Altinn 2, with a few extensions (presumably, I'm not too familiar with Altinn 2). In Altinn 2, the validation model is based upon the intended app flow where the user fills inn relevant information into form fields, and when reaching the end of the form they click a button ("Kontroller skjema") to run the entire form through validation (meaning schema validation runs, and potential custom validation). In Altinn 3 we also run full valdation at the end of the form submission, but it happens implicitly when the user clicks the submit button, and we prevent the submission and present the user with validation messages in the bottom of the form, around the submit button, telling them what they have to fix before sending in. See screenshots in Altinn/app-frontend-react#100. In addition to that, we have some extra possibilities:
Problems1a. Single field validation is hard to get rightReferences:
In short, it's very difficult for app developers to write backend code that works the way they probably expected it to work. Since we re-use the same endpoint for both regular instance/data model validation and custom single field validation, it is very easy to write validation logic that either:
This is related to 1b, because a solution to this could be to provide better interfaces to work with on the backend, and make validations declarative in a way that makes it possible to know which validations ran and were OK for each validation trigger/run. 1b. Having to use
|
With all that said, me and @tjololo had a discussion about a few of these, and I think we've landed on a better path going forward. Key takeaways from that discussion:
In addition to this discussion with @tjololo, we had a meeting about the future of validation as well. Some thought that came up there includes:
|
I would like to highlight a few issues related to how we store validations in the frontend.
|
Good points! I think solving both of these in Altinn/app-frontend-react#1506 should be at least looked into.
Agree!
Good point. I guess that was "solved" by duplicating the validation in the state we have now, but I don't think that's the right solution. We should instead try to find the first available (non-hidden) component we can navigate you to, and if the user cannot fix the problem there, they're on their own. I guess that would be a limitation in our apps we would expose more clearly by storing the state this way, and if we want to at a later point we could add a new property to validation issues indicating which component we should focus/navigate to when the user clicks to fix the validation. |
I'll add some notes about what I've been thinking lately about our future direction re: validations. Right now, as the configuration is often based on triggering validations, we've ended up with some of the problems I have described above. The solution I've envisioned, extends our current validation data types this way: enum ValidationUrgency {
// The validation message shows up immediately, even when the user is typing
Immediate = 10,
// Shows up when the user has stopped typing for a while (defaults to 400ms, but can be configured
// using `saveWhileTyping` property on the component).
AfterTyping = 15,
// Shows up when the user moves focus out of the field
OnBlur = 20,
// Shows up when the user tries to 'save and close' a repeating group row. Only affects form fields inside
// the repeating group row (validating all rows in the group at the same time was most likely a mistake in
// when implementing `validateGroup`, so I think we're safe to ignore that case).
OnGroupRowClose = 30,
// Shows up when the user tries to navigate beyond the current page (finally regardless of the
// component used to do it!). The user can still navigate to the previous page without getting the
// validation message.
OnPageNext = 35,
// Shows up when the user tries to navigate away from the current page. It would not be possible to
// navigate to the previous page without getting the validation message (and be blocked from navigating).
OnPageNavigation = 40,
// Shows up when the user tries to submit the form. At this point page navigation cannot be blocking, as
// the user would not be able to go back and fix the validation issues.
OnFormSubmit = 50,
}
interface NewValidationIssue extends BackendValidationIssue {
urgency: ValidationUrgency;
}
interface ValidationGroups {
[group:string]: BackendValidationIssue[];
} Right now the validation endpoints returns The next part here is the extension of As @ivarne has mentioned, it's kind of weird that we have to run validation as a separate step after saving. I agree with him that validation issues (or, I think this solution fixes most issues:
|
After having written this down, it became clear for me that some of these urgencies implicitly prevent page navigation (or navigating out of a repeating group row), while others do not. Instead of tying when the validation message should appear to the user with which actions should the user now be allowed to do, we should consider decoupling these. But then again, maybe it never makes sense for a validation message to have an urgency of EDIT: Maybe it could be made more clear to app developers in naming and documentation: enum ValidationUrgency {
// Does not block anything
Immediate = 10,
AfterTyping = 15,
AfterBlur = 20,
// Block some form of navigation
BeforeGroupRowClose = 30,
BeforePageNext = 35,
BeforePageNavigation = 40,
// Does not block any navigation
OnFormSubmit = 50,
} |
Some thoughts on custom validation in the backend, which I don't think have been covered here. Currently, we use a More importantly, the same limitation exists for Task validation. However, in that case; you are not even validating form data and so using a tagging @ivarne and @olemartinorg in case you have some thoughts on this 🙂 |
Description
This epic describes the future direction and principles which validation issues should be based upon in order to solve the major challenges we see with validation today.
Challenges today
Frontend and backend both validates input but don't always agree
Today frontend validates the data model against the Json Schema and backend validates against the strongly typed C# class with attributes based on the XSD. While all originate from the same source (Json Schema) there might end up being small differences like a large number that validates against the Json Schema, but fails against the strongly typed C# model. Also custom validations (in backend) will in the case of field triggering override the validation done in frontend, meaning you will have to reimplement any frontend validation logic.
Altinn/app-frontend-react#279
Datamodel restrictions vs component validation
We have two levels of validation. One is to adhere to the restrictions set on the data model and the second is validation rules defined on the component level. While both needs to be there and respected, we should have a clear definition of the order, the originating source of the error and which part is responsible for what kind of validation.
Dependent on custom validation in backend
If you need custom validation, the only way to add this is by resolving to C# and coding it in the backend. This makes the bar higher than necessary for application developers who should be able to express this as rules using the expression language in json configuration or in Altinn Studio.
Implementation goals
Only involve backend validation when strictly needed
This means that frontend should be able to validate as much as possible on it's own and that backend should only be involved in the last step when submitting the data as a final safe guard when submitting the data. This also means we to some level need to extend the support for custom validation to frontend.
Opt-in when you need special validation
If you need to resolve to custom validation in the backend this should be (as today) a choice for the developers. However the implementation should probably change a bit towards small validation interfaces with easy access to necessary information like what page triggered the validation, what component, what was the previous value, what is the new value etc.
Standardized validation messages
Validation messages should be based on the Problem Details for HTTP APIs. Validation problem messages should contain the originating source of the error (custom, data, serialization) to allow frontend to make a decision on how to handle them and other required information ref. todays
ValidationIssue
class.Extend the current expression language with validation support
In order to allow more validation in the frontend we need to support the use of expressions when configuring components. These should run in the frontend by default, and in backend as part of the validation done when submitting data.
Altinn/app-frontend-react#726
Validate data model against the same Json Schema in frontend and backend
In order for frontend and backend to be consistent in the data model validation we should preferably validate against the same schema. We still need to address XSD validation as an option to enable as this is critical for some applications depending on XSDs.
Altinn/app-lib-dotnet#197
Validation of composed components
Some components consists of multiple fields. When we do component validation today we don't know which of these fields that has a problem. We should know which field and be able to provide different validation rules for different fields in components composed of multiple fields.
Scope
In scope
No response
Out of scope
Validation of application configuration/state
This issue addresses form validation and not validation of the state of an app ie. are all configuration files valid, are there missing text resources etc.
Additional Information
Tasks
No response
Tasks
source
field app-frontend-react#1386Source
toValidationIssue
app-lib-dotnet#287The text was updated successfully, but these errors were encountered: