Vee-validate: Add a way to get all errors to ValidationObserver

Created on 27 Aug 2019  Â·  14Comments  Â·  Source: logaretm/vee-validate

Is your feature request related to a problem? Please describe.
I really like the changes in v3. It's solved a lot of the issues with componentizing forms (no more inject!) and displaying errors, etc. However, I keep wanting to have some concise way to get all the errors on the page. Either for debugging or for displaying the first error on submit or scrolling the form back up to the error message, etc.

Describe the solution you'd like
Add getErrors or some other interface to ValidationObserver to get some sort of error list. validate and setErrors already exists so it would seem natural to add a getErrors.

Describe alternatives you've considered
The validate method could return more than true/false but that seems a bit kludgy. An error-model or something similar could be used to store errors based on events.

request ✨ enhancement

Most helpful comment

@d3radicated, I try to check "this.$refs.observerRef.errors" right after validation() execution (in 'then' section), and it is empty. But if I set timeout to 100ms this.$refs.observerRef.errors has filled with correct error descriptions.
If I try to get errors through ValidationProvider ref, all is Ok and I get errors immediately.

this.$refs.observerRef.validate().then(isValid => {
    console.log('isValid', isValid); // false
    console.log(this.$refs.observerRef.errors); // { Field: Array(0) }

    console.log(this.$refs.providerRef.errors); // ["Field is not valid."]

    this.$nextTick(() => {
        console.log(this.$refs.observerRef.errors);  // { Field: Array(0) }
    });

    setTimeout(() => {
        console.log(this.$refs.observerRef.errors); // { Field: Array(1) } <- correct error values here  
    }, 100);
});

Look like propagation errors from ValidationProvider-s to ValidationObserver is async task

All 14 comments

Currently, you can get the errors from the slot scope of the observer. Or using $refs.observerRef.ctx.errors.

But I will think of a better way to get it soon.

Currently, you can get the errors from the slot scope of the observer. Or using $refs.observerRef.ctx.errors.

But I will think of a better way to get it soon.

$refs.observerRef.ctx.errors is helpful, thanks. It's definitely not ideal since it returns all the inputs even if they have no errors. And the values are indexed on _vee_n which doesn't really apply to anything on the page.

Current workaround until a better way is published:

this.notifications = Object.values(this.$refs.observer.ctx.errors).flat();

This will ignore the _vee_n keys and will flat their values (validation messages) into a final array.

Seems like strictly related, so I'm going to put it here instead of creating separate issue:

While the above workaround is working for getting errors of all fields, similarly it would be useful to more easily get list of errors for given field. Currently indexing them by _vee_n is completely not useful, so the only solution is to wrap every field with ValidationObserver which is a lot of boilerplate.

I imagine that it should be either possible to get errors by name or vid from top-level observer or use ValidationProvider similiarly as ValidationObserver for that purpose, so that I can write something like that: this.$refs.usernameProvider.errors or this.$refs.formObserver.errors.username.

@apierzch I'm not sure why I introduced VID in the first place, that was a very long time ago 😣. I presume because I wanted to differentiate between the display name which will be used in errors and the actual id that will be used internally.

So far I experimented with using the name instead, first, it will check if the VID is provided and use it, otherwise, it will fall back to the name field if it exists, else it will generate a random ID like it currently does. And it seems to work fine so far.

Maybe instead of exposing the errors on the observer as a record by id, it will instead be a record by name and keep using whatever generated id internally.

+1 for a more handy way to get the errors of the observer.

On my end, it's more in the template that I need an improvement, but it's related.

Currently, the observer errors are an array like { vid => message }, so I experience two issues:

  • I want to know if a rule failed, and all I have is the vid and the rule message, but I need the rule name
  • there is no immediate way to get the first error since Objects have no methods for getting their first property AFAIK (although object keys have an order in modern browsers), so I use a function of my own. Not a big deal but I'd expect an array.

So I thought it would be nice to have the failedRules on the observer too, in the form:

failedRules = [
  { field: 'vid1', name: 'myrule1', message: 'my error message' },
  { field: 'vid1', name: 'myrule2', message: 'my other error message' },
  ...
]

Maybe a getErrors method could return the same thing.

By the way, I haven't tested but since a field can have several errors with bails, and that the errors are currently keyed by the vid, I guess the current format only returns the first error of each field?

Release 3.1.0 seems to have broken error retrieval via $refs.observerRef.ctx.errors. The object is empty. I assume that's due to the change to debouncing ValidationObserver updates? Is there any way -- preferably a promise -- we can find out when the errors field is ready for reading?

@mpaluchowski The errors are now moved as data on the observers (as stated here).

@d3radicated thanks for pointing that out. $refs.observerRef.errors also is empty :disappointed:

If you would like to get errors after validation,

this.$refs.observerRef.validate().then(() => {
    console.log(this.$refs.observerRef.errors);
})

@d3radicated, I try to check "this.$refs.observerRef.errors" right after validation() execution (in 'then' section), and it is empty. But if I set timeout to 100ms this.$refs.observerRef.errors has filled with correct error descriptions.
If I try to get errors through ValidationProvider ref, all is Ok and I get errors immediately.

this.$refs.observerRef.validate().then(isValid => {
    console.log('isValid', isValid); // false
    console.log(this.$refs.observerRef.errors); // { Field: Array(0) }

    console.log(this.$refs.providerRef.errors); // ["Field is not valid."]

    this.$nextTick(() => {
        console.log(this.$refs.observerRef.errors);  // { Field: Array(0) }
    });

    setTimeout(() => {
        console.log(this.$refs.observerRef.errors); // { Field: Array(1) } <- correct error values here  
    }, 100);
});

Look like propagation errors from ValidationProvider-s to ValidationObserver is async task

Workaround from @sin314 works!

What's the status of this?
setTimeout solution is not production ready..

Tagged in 3.4.0 The validate function now automatically updates the state of the observer so timeouts are no longer neccessary after validate.

this.$refs.observerRef.validate().then(isValid => {
    console.log('isValid', isValid); // false
    // will be updated
    console.log(this.$refs.observerRef.errors);
});

validateWithInfo is also a new function available on observers, it gives you access to all errors in it's fullfilled callback.

this.$refs.observerRef.validateWithInfo().then(({ isValid, errors })=> {
    console.log('isValid', isValid); // false
    console.log(errors);
});
Was this page helpful?
0 / 5 - 0 ratings