In Vue and Vue Router SPA, showing 404 for a not found resource

10,036

Solution 1

You need to set a route for 404 page and then redirect unmatched routes to it. I use a router.redirect after the map to do such things.

router.map({
  '/': { name: 'home', component: HomePage },
  '/foo/:id': {name: 'foo-show', component: FooShowPage},
  '/404': {name: 'not-found', component: NotFound}
})

router.redirect({
    '*': '/404'
})

All routes that are NOT listed in the map will then be redirected to /404

Solution 2

Found a solution at Vue.js forum — use navigation guard:

import store from '../store'

{
  path: '/lavori/:lavoro',
  name: 'lavoro',
  component: Lavoro,
  beforeEnter: (to, from, next) => {
    function isValid (id) {
      return store.getters.resourceByID(id) !== undefined
    }

    if (!isValid(to.params.id)) {
      next({ name: 'not-found' });
    }    
    next();
  }
},

Edit1: need to import store to get access to getters, from this Github issue and this question

Still a question how to leave same (requested) URL

Share:
10,036
harryg
Author by

harryg

Software engineer for 🌳 energy ⚡️ provider. I work mostly with TypeScript in React and the server. I am a strong proponent of functional programming and as well as writing functional code in my day-to-day projects I also enjoy learning and tinkering with "purer" functional languages such as Elixir, Elm, Haskell and PureScript.

Updated on June 11, 2022

Comments

  • harryg
    harryg almost 2 years

    I'm using Vue and Vue Router in a SPA. In a view component I query a repository for a resource. If the resource is not found I want to show a 404 page whilst keeping the URL.

    I.e. if I visit /foo/non-existant-id then a 404 page should be shown in place of the show page for the foo resource.

    For clarity here is my router map:

    router.map({
      '/foo/:id': {name: 'foo-show', component: FooShowPage},
    
      // Utilities
      '/': { name: 'home', component: HomePage },
      '*': { name: '404', component: NotFoundPage }
    })
    

    And in my FooShowPage I do the following:

    ready () {
      // fetch the foo from the repo (app.foos)
      app.foos.fetchById(this.$route.params.id).then(foo => {
        this.foo = foo
      }).catch(e => {
        // foo is not found show a 404 page
        // using this.$route.router.go({name: '404'}) does not work as route is a wildcard 
        console.warn(e)
      })
    }
    

    Essentially it would probably involve replacing the FooShowPage in the router view with NotFoundPage, or redirecting to a defined 404 page whilst keeping the browser history untouched.