← Back to blog

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

| VueJS

Handling Laravel validation errors on a Vue.js 3 front end sounds straightforward, but it becomes tedious fast once you have more than a couple of API calls.

Here is how axios handles errors:

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

Using the catch method in axios, you can present errors to the user. If you only have one or two API calls, handling error messages individually works fine. But when you have a dozen API calls, repeating that logic in every catch block is a waste of time.

axios offers a feature called interceptors that intercepts requests or responses before they reach then or catch.

Here is what that looks like:

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);
});

Now let us put this into practice.

In my project, I have a file named http.js that serves as 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 do not already have something like this in your project, create one. It saves you from repeatedly importing and configuring axios everywhere.

Here is how to use the http helper:

import http from "@/services/http";

http.get('api/users');

Clean and simple.

For displaying notifications, I use the vue-toast-notification package. Let us integrate it with axios to handle validation errors automatically.

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);
    }
}

The Notify class can now be used from anywhere in the project:

import Notify from "@/services/notify";

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

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

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;

From this point on, the interceptor handles all validation error messages and displays them to the user automatically.

You can still access the error object inside the catch method because the interceptor returns Promise.reject.

Summary

  • Centralized HTTP client -- create an axios helper file so you configure headers, base URL, and credentials in one place.
  • Interceptors over repetition -- use axios response interceptors to handle validation errors globally instead of duplicating logic in every catch block.
  • Toast notifications -- wrap a toast library in a Notify class for a consistent, reusable notification API across your project.
  • 422 status check -- specifically target Laravel's 422 validation response status and extract the error messages from error.response.data.errors.
Share