Skip to content

12. Example [nuxt-09]: controlling navigation

The example [nuxt-09] uses a middleware to control the client’s 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.

The example [nuxt-09] is initially obtained by copying the 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 URL or [/nuxt-09/abcd]. Since the page [abcd] does not exist, the page [_.vue] will be displayed. Here, it will be the following:

Image

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


<!-- definition HTML of the view -->
<template>
  <!-- layout -->
  <Layout :left="true" :right="true">
    <!-- alert in the right-hand column -->
    <template slot="right">
      <!-- message on yellow background -->
      <b-alert show variant="warning" align="center">
        <h4>La page demandée n'existe pas</h4>
      </b-alert>
    </template>
    <!-- navigation menu in the left-hand column -->
    <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 code for the [client-routing] client middleware is as follows:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function({ route, from, redirect }) {
  // only the customer
  if (process.client) {
    console.log('[client-routing]')
    // desired navigation order
    const routes = ['index', 'page1', 'page2', 'index']
    // current route
    const current = route.name
    // previous route
    const previous = from.name
    // we want a circular navigation
    // routes[i] to routes[i+1]
    for (let i = 0; i < routes.length - 1; i++) {
      if (previous === routes[i] && current !== routes[i + 1]) {
        // we stay on the same page
        redirect({ name: routes[i] })
        return
      }
    }
  }
}
  • line 3: we know that the routing function receives only one parameter, the [context] object from the entity executing it, whether server or 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 [route, from, redirect] parameters 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 routing;
  • line 12: the name of the previous page in the current routing;
  • line 14: as an exercise, we will only allow a circular navigation [index --> page1 --> page2 --> index];
  • lines 15–21: we iterate through the array giving the order of the desired navigation;
  • line 16: if we find that routes[i] was the last routed page, then the next one must be routes[i+1];
  • lines 18-19: if this is not the case, redirect the application to routes[i], i.e., do not change pages: reject 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 page [Page 2], you can only navigate to page [Home];
  • when you request an incorrect URL, such as [http://localhost:81/nuxt-09b/abcd], you will see a page indicating that the requested page does not exist;