vue-formulate
vue-formulate copied to clipboard
Unable to get form errors from inside nested form group
If you have a form group with nested form fields, how do you get the errors on those form fields?
If I bind a handler to the parent form, like this:
<formulate-input @validation="myValidationEvent"> ...
If I log the output from that event to the console, the output for a normal form field looks this this:
{name: 'personalDetails', errors: Array(1), hasErrors: true}
where errors
is an array containing the errors. But if I do the same for a form group, I get this:
{name: 'personalDetails', errors: Array(0), hasErrors: true}
Note the empty errors
array – this seems like a bug. How do I get to the errors on the form fields nested inside the group?
Generally I discourage developers from trying and explicitly access the validation messages and maintain their own state — Vue Formulate is built to handle just that problem, but in a few cases people have needed to revert to using the validation event as an escape hatch for some side effects they want to run. So my first question is — do you really need those messages?
In regards to your specific question — where did you put the validation listener — on the <FormulateInput type="group">
? Keep in mind that the group
input is an input itself that can have it's own validation rules — so you don't automatically get inherited values from children of that group — you can always bind the @validation
event on children of a group explicitly too — but again, sorting out the state on all that stuff gets kinda complicated — the juice might not be worth the squeeze.
As an aside that is worth noting — FormKit (the next major version) has a completely different internal mechanism for working with groups that is dramatically better that the current status quo.
Thanks for the quick reply!
Yeah, maybe it's a bit of a smell on my end. The use case is to display a single list of warnings at the very end of the form, as the form we have is very long and complex, so a summary of any missing fields/validation warnings is useful. Is there a way of doing this that doesn't involve me directly grabbing the errors in this way?
The listener is on the parent form that the form group is inside. I get the same result with the listener on the form group itself. Am experimenting with putting the listener on the form group's inputs directly, but this seems bad.
There's an easy to use solution that gets you part of the way there, but not with the specific validation messages. If you put the <FormulateErrors />
component near the bottom of your form (I usually do it right above the submit button) you can add a message to display when any errors are detected in the form and someone tries to submit. This is for this exact use case (long forms), but it falls short of actually delivering the specific messages that are failing. Partly this is by design since validation messages are written to be displayed in context. For example a validation message might something like "this field is invalid" which is unhelpful when it's displayed in a rollup at the bottom of the screen.
If you really need to show the specific messages though, you'll need to do some work like binding to the @validation
handler or using a ref
to get a hold of the context object explicitly to access them.
FYI it's the invalid-message
prop on the form: https://vueformulate.com/guide/forms/#form-validation
Thanks so much for your help with this, Justin! Happy to close this out (or can leave it open if you think this is a genuine bug).
@henryaj I had this same issue (I need to display a list of all errors in the form). The solutions provided above just don't work well for grouped data.
I created a custom component that loops over the failingFields
data of the form to create a list of errors.
To get the form errors data, I created a simple watcher like this:
mounted () {
this.$watch(
() => (this.$refs[this.formId] as any).failingFields, // add a ref to your form
(value: Record<string, any>) => {
this.failingFields = value // create a failingFields object in data()
}
}
)
You can then use the failingFields
data to help list out the errors. Obviously your use case will need more work on top, but hopefully, this helps. Let me know if you need more info