Skip to content

12. Example [nuxt-09]: Controlling Navigation

Example [nuxt-09] uses a middleware to control client navigation. Additionally, a new view is added for cases where the user requests a URL from the server that does not exist in the application.

Example [nuxt-09] is initially created by copying example [nuxt-01]:

Image

12.1. The [_.vue] page

We mentioned that the application’s routes are built from the contents of the [pages] folder. Here, we have added the [_.vue] page to this folder. This specific page is displayed whenever the application is routed to a page that does not exist. In our example here, this cannot happen for the client. But it can happen for the server if, for example, it is asked for the URL [/nuxt-09/abcd]. Since the [abcd] page does not exist, the [_.vue] page will be displayed. Here, it will look like this:

Image

The code for the [_.vue] page is as follows:


<!-- définition HTML de la vue -->
<template>
  <!-- mise en page -->
  <Layout :left="true" :right="true">
    <!-- alerte dans la colonne de droite -->
    <template slot="right">
      <!-- message sur fond jaune -->
      <b-alert show variant="warning" align="center">
        <h4>La page demandée n'existe pas</h4>
      </b-alert>
    </template>
    <!-- menu de navigation dans la colonne de gauche -->
    <Navigation slot="left" />
  </Layout>
</template>
 
<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */
 
import Layout from '@/components/layout'
import Navigation from '@/components/navigation'
 
export default {
  name: '404',
  // components used
  components: {
    Layout,
    Navigation
  },
  // life cycle
  beforeCreate() {
    // client and server
    console.log('[404 beforeCreate]')
  },
  created() {
    // client and server
    console.log('[404 created]')
  },
  beforeMount() {
    // customer only
    console.log('[404 beforeMount]')
  },
  mounted() {
    // customer only
    console.log('[404 mounted]')
  }
}
</script>

12.2. The client middleware

The client middleware code [client-routing] is as follows:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function({ route, from, redirect }) {
  // seulement le client
  if (process.client) {
    console.log('[client-routing]')
    // ordre de navigation souhaité
    const routes = ['index', 'page1', 'page2', 'index']
    // route courante
    const current = route.name
    // route précédente
    const previous = from.name
    // on veut une navigation circulaire
    // routes[i] vers routes[i+1]
    for (let i = 0; i < routes.length - 1; i++) {
      if (previous === routes[i] && current !== routes[i + 1]) {
        // on reste sur la même page
        redirect({ name: routes[i] })
        return
      }
    }
  }
}
  • Line 3: We know that the routing function takes only one parameter, the [context] object of the entity executing it, whether it be the server or the client. The notation [function({ route, from, redirect })]
    • is equivalent to [function({ route:route, from:from, redirect:redirect })];
    • which means that { route:route, from:from, redirect:redirect } <-- context;
    • which creates three parameters [route, from, redirect] such as:
      • route=context.route;
      • redirect=context.redirect;
      • from=context.from;

The [nuxt] documentation makes extensive use of this notation. It is important to be familiar with it;

  • line 8: an array of page names in the desired navigation order
  • line 10: the name of the destination page for the current route;
  • line 12: the name of the previous page in the current routing;
  • Line 14: As an exercise, we will only allow circular navigation [index --> page1 --> page2 --> index];
  • lines 15–21: we iterate through the array to determine the desired navigation order;
  • line 16: if we find that routes[i] was the last page navigated to, then the next one must be routes[i+1];
  • lines 18–19: if this is not the case, we redirect the application to routes[i], i.e., we do not change pages: we reject the navigation;

12.3. Execution

We run the example with the following [nuxt.config.js] file:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: process.env.npm_package_name || "Introduction à nuxt.js par l'exemple",
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  },
  // source code directory
  srcDir: 'nuxt-09',
  router: {
    base: '/nuxt-09/',
    middleware: ['client-routing']
  },
  // server
  server: {
    port: 81, // default: 3000
    host: 'localhost' // default: localhost
  }
}

Check the following:

  • when you are on the [Home] page, you can only navigate to the [Page 1] page;
  • when you are on the [Page 1] page, you can only navigate to the [Page 2] page;
  • when you are on the [Page 2] page, you can only navigate to the [Home] page;
  • When you request an invalid URL such as [http://localhost:81/nuxt-09b/abcd], you get a view indicating that the requested page does not exist;