I'm trying to combine both frontend and backend validation.
For example, on a registration form where the user enters an email there's an email
validator on the frontend and a unique
validator on the backend.
If the backend fails then the error message is saved to a store in requestErrorMessage
.
{'email': 'A user with this email already exists.'}
The email value from the request is also saved in an errorValues
dictionary so that the error is automatically removed if the input is changed to a different value.
mixins: [validationMixin],
validations: {
email: { required, email },
password: { required, minLength: minLength(8) },
password1: { required, sameAsPassword: sameAs('password') }
},
data() {
return {
email: '',
password: '',
password1: '',
errorValues: {},
errorFields: [
'email',
'password',
'password1'
]
}
},
emailErrors()
checks if there's an error from the server. If there is then it gets added to any existing errors but only if the input value is the same as the value when the request was made (stored in errorValues
).
computed: {
...mapGetters('auth', ['requestErrorMessage']),
emailErrors() {
let errors = []
const field = 'email'
const serverError =
Object.keys(this.requestErrorMessage).includes(field) &&
this[field] === this.errorValues[field]
if (!this.$v[field].$dirty) return errors
!this.$v[field].email && errors.push('Must be valid email')
!this.$v[field].required && errors.push('Email is required')
if (serverError)
errors = errors.concat(this.requestErrorMessage[field])
return errors
}
},
So everything above is working as expected but the error isn't visible until the user changes the input then changes it back to match errorValues.email
. In other words, it seems like this.$v.$touch()
isn't working.
methods: {
...mapActions('auth', ['register']),
handleSubmit() {
const data = {
email: this.email,
password: this.password,
password1: this.password1
}
this.register(data).then(success => {
if (!success) {
Object.keys(this.requestErrorMessage).forEach(key => {
if (this.errorFields.includes(key)) {
this.errorValues[key] = this[key]
}
})
this.$v.$touch()
}
})
}
}
How can I get the server validation error to show after the promise is returned without the user manually modifying the input?
Just had to $reset
to set the $dirty
flag to for all children to false
before before calling $touch
.
this.register(data).then(success => {
if (!success) {
Object.keys(this.requestErrorMessage).forEach(key => {
if (this.errorFields.includes(key)) {
this.errorValues[key] = this[key]
}
})
this.$v.$reset()
this.$v.$touch()
}
})