Exploring the Functionality of Using Multiple Middlewares in Vue.js 3

For my web app project using vue.js 3 and vue-router, I followed a helpful tutorial on implementing middleware pipelines. The tutorial can be found at: https://blog.logrocket.com/vue-middleware-pipelines/. This tutorial demonstrated creating middleware to prevent unauthorized access, as well as using multiple middleware for a single route structure like this:

children: [{
                path: '/dashboard/movies',
                name: 'dashboard.movies',
                component: Movies,
                meta: {
                    middleware: [
                        auth,
                        isSubscribed
                    ]
                }
            }],

In the tutorial, each middleware function calls the "next()" function once, but what if you need to call it multiple times for different purposes? Vue.js 3 documentation suggests using the "next()" function only once. How can we effectively implement multiple middlewares in vue.js 3 similar to the approach shown in the aforementioned tutorial?

Answer №1

If you're facing challenges with implementing middlewares in Vue3, here is an approach that might help:

// authentication middleware
import { useAuthStore } from "@/stores/auth";

export default async function auth({ next }) {
  const authStore = useAuthStore();
  
  const user = await authStore.checkAuth();

  if (!('id' in user)) {
    console.log("Not logged in");
    return next({
      name: "Login",
    });
  }
  return next();
}

Another middleware example:

// city selection middleware
import { useCitiesStore } from "@/stores/cities";

export default function hasCity({ next }) {
  const citiesStore = useCitiesStore()

  if (!citiesStore.city) {
    console.log('City not selected')
    return next({
      name: 'CitySelector'
    })
  }
  return next();
}

Incorporating the middlewares within the router:

import auth from '@/middlewares/auth'
import hasCity from '@/middlewares/hasCity'

// other imports and code

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      layout: 'default',
      middleware: [auth, hasCity]
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: Login,
    meta: {
      layout: 'blank'
    }
  },
  {
    path: '/city-selector',
    name: 'CitySelector',
    component: CitySelector,
    meta: {
      layout: 'blank'
    }
  }
];

const router = createRouter({
  routes,
});

function nextFactory(context, middleware, index) {
  const nextMiddleware = middleware[index];
  
  if (!nextMiddleware){
    return context.next;
  }
  const subsequentMiddleware = nextFactory(context, middleware, index + 1);
  return nextMiddleware({ ...context, next: subsequentMiddleware })
}

router.beforeEach((to, from, next) => {
  if(!to.meta.middleware){
    return next();
  }

  const middleware = Array.isArray(to.meta.middleware)
    ? to.meta.middleware
    : [to.meta.middleware];
  const context = {
    to,
    from,
    next,
    router,
  };

  return middleware[0]({ ...context, next: nextFactory(context, middleware, 1) });

});

export default router;

Answer №2

If you're looking for a seamless implementation without the need for configuration, consider using vue-middleware.

Check it out on Github: https://github.com/themustafaomar/vue-middleware

Explore the documentation here:

Here's an example of how it can be used:

{
  name: 'dashboard',
  path: '/dashboard',
  component: () => import('@/layouts/dashboard.vue'),
  meta: {
    middleware: 'dashboard',
    // or using array syntax..
    middleware: ['dashboard', 'logger'],
  },
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Features of ES2015's [[class]] attribute

I've been developing a basic clone function var shallowCopy = function (value) { // In ES2017, we could also use // return Object.create(Object.getPrototypeOf(value), Object.getOwnPropertyDescriptors(value)); let propDescriptors = {}; for (le ...

Ensure the div element remains fixed at the top of the page

I created a script to identify when I reach the navigation bar div element and then change its CSS to have a fixed position at the top. However, I am encountering an issue where instead of staying fixed, it jumps back to the beginning of the screen and fli ...

Using Vuetify to populate a selection menu with options from a JSON array containing objects

I am facing a challenge while trying to populate a Vuetify v-select component with data from a REST API JSON response. Below is the current code I have been working on. While populating the list using a simple array is easy, I am struggling to set both the ...

Unfortunately, the datepicker feature does not seem to work properly on elements that have been dynamically added through the

My code progress so far is as follows: $('body').on('change', '.dropdown', function() { $.ajax({ success: function(res) { if(res.success == true) { return elements that have the class ...

An easy guide to rerouting a 404 path back to the Home page using Vue Router in Vue.js 3

Hello amazing community! I'm facing a small challenge with Vue.js 3. I am having trouble setting up a redirect for any unknown route to "/" in the router. const routes = [ { path: "/", name: "Home", component: Home, }, { path: "* ...

Include form data into an array of objects within an Angular data source

I am struggling to add the edited form data from edit-customers-dialog.ts into an array of objects in my datasource. The form.data.value is returning correctly, but I'm facing issues with inserting it properly into the array. As a beginner in Angular ...

Are there options available in nightwatchjs for making intricate decisions with selectors?

When using the NightWatch JavaScript Selenium tool, it is important to establish good practices for identifying different parts of the GUI before running tests. For example, distinguishing between options A and B and creating separate tests accordingly. An ...

Creating an AJAX XML tree without the need for a backend server language

My goal is to create a nodes tree using the information from a data.xml file, similar to what is demonstrated in this example, all done through AJAX. Can this be accomplished without utilizing a server-side programming language? I have access to the enti ...

Ensure to trigger the Ajax function prior to the tab change event in a Vue form wizard

I'm currently utilizing the Vue wizard from https://www.npmjs.com/package/vue-form-wizard and I need to trigger an AJAX function before the tab change event like so: beforeTabSwitch: function(tab){ if(tab===2) { this.formData .post(APP_URL ...

VueJS Vuetify automatically centers default content

Vue cli version @ 5.0.6 | Vuetify version: [email protected] I have been utilizing Vue.js and Vuetify for some time now, and I can't shake the feeling that not all Vue.js/Vuetify components default to centered alignment. I recently initialized a ...

What could be causing the recurring appearance of the success alert message in an AJAX call to a PHP script in this particular situation?

Below you will find two code blocks, each designed to handle an AJAX call to a PHP file upon clicking on a specific hyperlink: <script language="javascript" type="text/javascript"> $(".fixed").click(function(e) { var action_url1 = $(th ...

Utilizing Facebook's JavaScript SDK to transmit variables to PHP using ajax

Thank you in advance for your attention. I am trying to utilize the Facebook js SDK to retrieve the user's name and id, and then send them to PHP on the same page (index.php). After successfully obtaining the username and id and storing them in two Ja ...

Ways to reposition arrows upwards in Vuetify carousel

Looking for help on adjusting the position of arrows in a carousel made with vuetify. I need to move both arrows up by setting top:0 in both v-window__next and v-window__prev classes, but unsure how to apply this property to the component. This snippet re ...

What is the best way to send information from App.js to components?

In my project, I am working with App.js and a functional component called "uploadlist". The goal is to pass a 'custid' value from App.js to the uploadlist component. Here's what I have attempted: app.js: export default class App extends Com ...

Trouble uploading an audio blob as a base64 string using Google Drive API with the drive.files.create method - File ID could not be located

My current challenge involves sending an audio blob to a specific Google Drive folder. To accomplish this, I convert the blob into a file before initiating the transfer process. However, I have encountered an error from the beginning: Error: File not fo ...

Adjust the active carousel item to 0 within onsen-ui (displaying a list of carousel items in a sliding menu)

In my sliding menu, each menu item contains a carousel with two items. I am trying to make the first carousel item show after closing and reopening the menu, or by clicking a button outside of the list on the menu page. This is my current setup: <ons- ...

How can I utilize jQuery to iterate through every anchor tag on an HTML page?

I am looking to reference all anchor tags on the page that have a parent h2 tag. To achieve this, I need to iterate through each anchor tag that has a parent h2 and add an attribute using jQuery. <body> <h1>not me</h1> <a href ...

Writing TypeScript, Vue, and playing around with experimental decorators

After creating a Vue project through Vue-CLI v3.0.0-beta.15, the project runs smoothly when using npm run serve. However, TypeScript displays an error message stating that support for decorators is experimental and subject to change in a future release, bu ...

retrieveValue() for SelectionDropdown

I have a simple task - I just need to retrieve the name of the Company and store it in the database. Initially, I was able to achieve this using plain text and the code snippet below: sport: this.refs.company.getValue(), which worked perfectly. However, ...

Obtaining objects from a Meteor collection on the server triggers a "Must have Fiber to proceed" error

As a beginner in creating meteor apps, I am working on a project that involves querying git issues from a specific repository. The goal is to generate tasks from these issues after retrieving them using the Github API. However, I keep encountering an error ...