All of the documentation around validation seems to be geared towards validating each field individually, rather than considering dependencies between fields. I found validation to be much much easier to grok in redux-form :(
Example: I have a form with a select, and an optional comment textarea. If one particular value in the select is chosen, then the comment actually becomes required.
Is the recommended approach to do this type of validation in a form reducer enhancer, looking for change action types and mutating the field errors (or whatever i want to call it) directly?
Is the recommended approach to do this type of validation in a form reducer enhancer, looking for change action types and mutating the field errors (or whatever i want to call it) directly?
Nah, it's actually much simpler than that! Here's how you would do form-wide validation:
<Form model="user"
validators={{
'': {
commentRequired: (user) => user.selectedComment || (user.comment && user.comment.length)
}
}}
>
The empty string in validators for <Form>-level validation means the entire form - it's as if you were validating the "user." model (which resolves to "user"), and the value passed into the validator would be the entire user model.
Thanks @davidkpiano - is that in the docs somewhere? Did I miss it? And how long has that been around? (We're still on 0.7.2 unfortunately)
Edit: ohhh, this is on the form component itself!
Yep! You're right though - I should add more specific documentation for form-wide validation.
So, I see this was added in 0.7.0. Using 0.7.2, I simply cannot get this to work.
The name of the model is 'skipCriteria'; the name of the model form is 'skipCriteriaForm'
<Form
model='skipCriteria'
validators={{
'': {
thisIsInvalid: (skipCriteria) => true
}
}}>
// .... fields here
I make changes to the fields themselves (which get reflected when I inspect the form props in react on 'skipCriteria'.)
I don't see the skipCriteriaForm prop change much at all. dirty gets set to true. I don't see thisIsInvalid getting set anywhere in skipCriteriaForm
Can you throw up an example on esnextb.in ?
Trying to, but having _major_ issues with esnextb.in right now.
Example:
http://esnextb.in/?gist=6b67a70889e949d7cbdc183c9e7053e2
I cannot get react devtools to work reliably with esnext, so I'm logging out the full props on each render. As you can see, I don't see commentRequired or reasonRequired showing up _anywhere_ in the skipCriteriaForm prop
Works fine with the latest RRF 0.13.1:

Can you not use the latest version?
I can try upgrading, though I am still trying to wade through all of the changes that have happened since early March to see what I need to look out for (hope that doesn't come off as ungrateful, it is just kinda tough to constantly be on top of every dependency these days)
Looks like the createFormReducer, createModelReducer renames & redux-thunk upgrade were the only changes I had to make :)
Yep! Until v1.0, no major changes are being made, only bug fixes. And even v1.0 won't have huge breaking changes, really. 馃槃
So, this is closed now, but - does the form "valid" property not actually get computed when following this approach? Do I have to manually consider:
valid = !skipCriteriaForm.errors.commentRequired && !skipCriteriaForm.errors.reasonRequred
To answer my own question, from the docs:
The .errors property of the model field is set: ...
... if validity is an object, .errors is set to the opposite of each validation key
I needed to actually invert my validation criteria (reasonRequired: true if reason is _not_ empty), etc
It does get computed.
.errors prop answers the question "Is this an error?" for each of its keys..validity prop answers the question "Is this valid?" for each of its keys.Oh, the difference between "is this valid" is that it is just a boolean, and "is this an error" being a boolean as to whether there is an error "description" for that field? Is that right?
So If I am using that '': {...} validator on the form component, that is _only_ setting validity, not errors, right?
To follow up: here is what I think is happening and is the source of my confusion:
Since the validator keys (reasonRequired, commentRequired) did not match the model attributes themselves, the valid prop on the form was _not_ getting recomputed correctly.
The function being invoked for each validation key should be answering the question "is this valid", so it should be returning true when that field/form is valid and false otherwise. So the keys in the '': { k: v } validator prop should really map to the real model field names.
I don't have an exact suggestion on how to rewrite it, but I think the validation docs could really use more clarification (it is extra tough when you are jumping between the description for "Form Component" and the general purpose description for "Validation")
Yeah, I will be clarifying it. Anyway, with validators in the <Form> component, the key/values of { '': { k: v }} no longer refer to fields; they refer to validation keys.
If you want them to refer to fields, they'd be on the first level of the object:
{
'': { /* form level validation */ }
firstName: { ... },
email: { ... },
}