6 Apr 2023

How to handle Laravel validation errors using VueJS 3, Axios, and Toast Notification

I came across a situation while working on my side project where I had to handle Laravel validation errors on the front-end application, which is built with VueJS 3. But, you might wonder why I am even writing an article about it since it seems like a straightforward task, isn’t it?

Let’s have a look at how axios handles the errors:

axios.get('/api/users')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    // Handle the errors
    console.log(error.response.data.errors);
  });

By utilizing the catch method in axios, you can present the errors to the end-user.

If you only have one or two API calls, then handling the error messages individually might suffice. However, what if you have a dozen API calls? It would be quite cumbersome to handle the error messages for each individual request.

Thankfully, axios offers a feature known as interceptors which, as the name implies, intercepts requests or responses prior to being processed by then or catch methods.

Let’s have a look:

axios.interceptors.response.use(response => {
	// Do something with the response
	// For example: Only return the data
  return response.data;
}, error => {
  // Handle the errors
  alert(error);
  return Promise.reject(error);
});

Let’s implement it.

In my project, I have a file named http.js which is an axios helper:

import axios from 'axios';

const client = axios.create({
  baseURL: import.meta.env.VITE_APP_API_URL,
  withCredentials: true, // required to handle the CSRF token
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
});

export default client;

If you don’t already have something similar in your project, I highly recommend creating an axios helper file, as it can save you the hassle of repeatedly importing and configuring axios every time it’s needed.

Here how I use the http helper:

import http from "@/services/http";

http.get('api/users');

Easy peacey.

On the other hand, I leverage the vue-toast-notification package for displaying notifications. As a result, let’s integrate it with axios to handle the validation errors.

First of all, you need to install vue-toast-notification - npm:

npm install vue-toast-notification@^3.0

Then create a file named notify.js:

import { useToast } from 'vue-toast-notification';
import 'vue-toast-notification/dist/theme-sugar.css';

const $toast = useToast({
    position: 'top-right',
    dismissible: true,
    duration: 2000,
});

export default class Notify {
    static success(msg) {
        $toast.success(msg);
    }

    static error(msg) {
        $toast.error(msg);
    }
}

At this point, the Notifyclass can be accessed from any location within our project:

import Notify from "@/services/notify";

Notify.error("An error ocurred!");

Go back to the http.js file and add the response interceptor as follows:

import Notify from "@/services/ui/notify";

client.interceptors.response.use(response => {
  return response;
}, error => {
  if (error.response.status === 422 && error.response.data?.errors) {
    Notify.error(Object.values(error.response.data.errors).flat().join("\n"));
  }

  return Promise.reject(error);
});

export default client;

Moving forward, the interceptor will manage all validation error messages and present them to the end-user in an appealing manner.

Please note that you can still access the errorobject within the catch method, which is why I am returning the Promise.reject.

That’s it.