Handling Error Responses Gracefully

Vue & Laravel

One of the fundamental parts of SPA design is setting up handlers to notify users of their request status in a recognizable manner. By Default Laravel will always return a “message” field in default responses. We can use this to our benefit if we follow the same design pattern.

Axios Interceptors

To get things rolling I setup an Axios response interceptor that will call my handleError function which gets passed the error object.


this.$http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
this.$http.interceptors.response.use((response) => {

//Store Current User
if(response.data.hasOwnProperty('currentUser')){
vm.setCurrentUser(response.data.currentUser)
}

//Toast Message
if(response.data.hasOwnProperty('message')){
Toast.create.positive({
html: response.data.message,
icon: 'fa-check-circle',
timeout: 2500,
})
}

return Promise.resolve(response)
}, (error) => {

vm.handleError(error)

return Promise.reject(error)
})

handleError() Method
In this example, I’m using Quasar Framework’s Toast Module to alert the user of the error response. If there is a sever error or DNS failure that inhibits the server’s response, you will not get a response at all. We must account for that in our handler by checking to see if there is a response before we try to handle it. In my example you can see I setup a Network Error as the default which will be overwritten with the actual response message when available.

*We can also catch an unauthorized request and $emit a logout event.

handleError(error){
   //Quasar Toast Schema
let message = {
html: 'Network Error.',
icon: 'fa-warning',
timeout: 2500,
}
   //Setup Error Message
if(typeof error !== 'undefined'){
if(error.hasOwnProperty('message')){
message.html = error.message
}
}

if(typeof error.response !== 'undefined'){

//Setup Generic Response Messages
if(error.response.status === 401){
message.html = 'UnAuthorized'
         vm.$emit('logout') //Emit Logout Event
      }else if(error.response.status === 404){
message.html = 'API Route is Missing or Undefined'
}else if(error.response.status === 405){
message.html = 'API Route Method Not Allowed'
}else if(error.response.status === 422){
//Validation Message
}else if(error.response.status >= 500){
message.html = 'Server Error'
}

//Try to Use the Response Message
if(error.hasOwnProperty('response') && error.response.hasOwnProperty('data')){
if(error.response.data.hasOwnProperty('message') && error.response.data.message.length > 0){
message.html = error.response.data.message
}
}
}

//Toast the Message
if(message.html.length > 0){
Toast.create.negative(message)
}
}
Quasar Framework Toast

Part 2: Validation Errors

Validation Errors

Laravel’s validator does a superb job dealing with complex validation requests and issuing the proper response. To use it, all we have to do it sync the validation response with our local Vue Module.

Reactive Error Data

I always setup an errors property in my reactive data to accept the synchronization.

data() {
return {
form: {
//fields
},
errors: {},
}
},

Validation Response Handler Mixin

We can use a mixin to add these methods to any Vue instance.

let ValidationResponseHandler = {
created() {
this.errors = {}
},
methods: {
syncErrors(error){
if(typeof error !== 'undefined'){
if(typeof error.response !== 'undefined' && error.hasOwnProperty('response') && error.response.hasOwnProperty('data')){
if(error.response.data.hasOwnProperty('errors')){
this.errors = error.response.data.errors
}
}
}
},
clearErrors(){
this.errors = {}
},
hasErrors(field) {
return this.errors.hasOwnProperty(field)
},
getError(field){
return this.errors.hasOwnProperty(field) ? this.errors[field][0] : null
},
getErrors(field){
return this.errors.hasOwnProperty(field) ? this.errors[field] : null
}
}
}
export default ValidationResponseHandler

ValidationResponse Mixin Usage:
To use the mixin, all we have to do is import it and assign it to the mixin property’s array.

import ValidationResponseHandler from '../your-path/ValidationResponseHandler'
mixins: [ValidationResponseHandler], //Vue Config
axios.post(route, data)
.then((response) => {
vm.clearErrors()
})
.catch((error) => {
vm.syncErrors()
})

ValidationResponse Field Helper Methods
Now that we have reactive error data, we can use it with the field helper methods included:

this.hasErrors('my_field') -> bool
this.getErrors('my_field') -> array
this.getError(‘my_field’) -> first of array
Quasar Framework Form

Dev Errors

When possible Laravel will give you an error response message which can be helpful during development.

Quasar Framework Toast