bmacnaughton
bmacnaughton

Reputation: 5318

How can I dynamically set destination component in Vue router

I am trying to dynamically set the target component for a vue-router route.

The reason is that I need to retrieve data from the server to know the correct component to target.

One solution I thought about was to add a global guard similar to:

router.beforeEach((to, from, next) => {
  get_data_from_server(to.fullPath).then(() => {
    // set the "to" component, but how?
    next();
})

But, as the comment says, how would I set "component" - there is no component property in the "to" object. (It looks like it is in components.default.render but that isn't documented and doesn't look like it should be messed with.)

Another alternative is to the use above logic but add special-case code to redirect but then I found there was no way to create a dynamic/new route that targeted the correct component.

How should one go about creating a route to a destination that is not known at build-time?

Upvotes: 3

Views: 1154

Answers (1)

bmacnaughton
bmacnaughton

Reputation: 5318

This solution seems to work.

router.beforeEach((to, from, next) => {
  get_data_from_server(to.fullPath).then(component => {
    if (to.matched.length === 0) {
      // the target route doesn't exist yet
      router.addRoutes({path: to.path, component: component})
      next(to.fullPath)
      return
    } else {
      // the route and component are known and data is available
      next()
    }
})

The key was finding the link in my comment above that shows the vue-router commit that implements addRoutes().

One thing to be aware of is that new routes are added at the end (makes sense) so any wildcards present might create unintended matches. I had a catchall route in place that redirected to a default page. But that matched before the newly added match because it was earlier the list. And that caused a stack overflow. In effect the code after if (to.matched.length === 0) is the default route.

Upvotes: 2

Related Questions