redux-form: Poll: Flatten Validation Errors?
This idea came from @clayne11’s excellent write-up on #1310.
There are a few problems with the current way that validation errors are returned:
- Array errors (
_error
) don’t work withImmutableJS
- Using
_error
for object and array errors is just gross.
What if we flattened the error object down to a map from field name to error?
Deep
This is the way we currently return errors:
const errors = {
test: {
_error: 'Awkward special rule'
foo: 'This is an error',
bar: 'This is another error',
},
foobar: 'An error',
anArrayField: [
{
test: 'This is not a valid value'
}
]
_error: 'This is a form wide error'
}
errors.anArrayField._error = 'Must have 3 entries'
Flattened
This is the proposed new way:
const errors = {
test: 'No longer awkward',
'test.foo': 'This is an error',
'test.bar': 'This is another error',
foobar: 'An error',
anArrayField: 'Must have 3 entries'
'anArrayField[0].test': 'This is not a valid value',
_error: 'This is a form wide error' // still needed :-(
}
This makes it trivial to represent errors at any depth in the form tree without having to rely on the magical _error
property.
Poll Question
Should we migrate to a flattened error structure for the v6.0.0
release?
Please vote with the 👍 buttons. And feel free to give reasons in the comments.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 48 (29 by maintainers)
Option 2
No. I love the flattened structure, but save it for
v7
. Just releasev6
already! :shipit:Option 1
No, I prefer the deep error structure.
Option 3
Yes, I think it is worth adding another breaking change now before release.
I would be wary of adding more indirection via strings (unless that’s the route you’re already taking I guess). This makes the library more incompatible with static typing (Flow or TypeScript).
I think flattening them might be a mistake. It seems like it will require the api to make assumptions about error format we want back. In a way, it seems like it aggregates the errors which means we’ll lose details for the sake of making displaying the errors easier. Keeping the errors in a more verbose “deep” format allows me to flatten them myself the way I want to in a way that makes sense for my app instead of having an abstraction do it for me.
And I think the helper method idea works, but the default should be to keep the errors in the more deep way, then the helper can flatten them.
@kristian-puccio How about:
That has been considered before as well.
I do like the idea of providing a helper to convert between the two formats to minimize migration pains.
Edit: Wow, so the 👎 button works, too. 😆 It wasn’t really a serious suggestion.
I would personally prefer the deep format as I find it much easier to work with and rationalize about an error result that has the same structure as my input (or as similar as possible)
How about an alternative error format that has a set structure? Example returning an object with
{$error: *, $values: *}
should pass the$error
to the validation parent and continue traversing on the$values
Example given the following structure:
The validation method could look very similar to the input:
The format can easily be improved with a helper function that returns the error only if one of the children is invalid (though implementing this could be an exercise to the user)
Using the above would result in the entire validation looking like:
EDIT: I also think this would have a much less performance impact than any flattened since there wouldn’t have to be any key parsing
Just release v6 already! :shipit:
My vote was all about that. Let’s make redux-form great again! 😈
Did any code changes come out of this discussion? Was a flattening function added?
I don’t have a strong opinion about the error structure, but what I would like to see is some easy way I could get an object where its keys match exactly the
name
attribute of the invalid input controls of the form. Then I can easily get a reference to the input control and do something with it like set focus on it.If there isn’t a built-in way to convert the error structure (as returned by
onSubmitFail
) into the flattened structure mentioned above, I’ll be glad to create one. (Actually, I already created it. See #2365.)So if the only real problem is arrays in Immutablejs, how about only allowing objects?
What also worries me is that flattening the object also breaks the concept of separation of concerns between different validation methods.
With nested you could do:
In the above, every method only knows about the input is given and their result only affects the input.
Using a flattened error object, this separation breaks and it’s possible for one method to overwrite the errors of any other fields:
Yes, you can build helper methods that pass the context and prepends it to the resulting keys, but this approach creates an ability to shoot yourself in the foot where previously there was none.
You don’t have to parse them - you’re creating them. And they don’t have to be parsed by
redux-form
either, as the key will be an exact match to the name of the field it’s grabbing the error for.I’m not sure if
redux-form
actually supports object errors at all at the moment. I know it used to only support strings.That being said, nothing would change in that case. We’re not saying you have to flatten the error objects themselves. We’re talking about flattening the error keys not the error values.
Error values are purely in user-land, whereas as error keys are part of the library’s design decisions.
If we do go with the flattened structure maybe provide some help functions aka lodash style so you can choose to work in either fashion.
Or maybe provide a function to apply the errors full stop.
Maybe:
I don’t think my code above is right but hopefully you get the idea. Basically we’re using an object as an api to describe error state at the momment but maybe that could be expressed as parameters to a function. Which of course would return an object in whatever fashion it chooses.