Vue-router: children named routes and empty path not rerendering

Created on 22 Oct 2016  路  7Comments  路  Source: vuejs/vue-router

Hello !

found another bug related to children routes and empty paths.

On this jsFiddle:
https://jsfiddle.net/p7uk1pbv/6/
click the 3 links in the jsfiddle one after another in the order: 1, 2, 3

  • (1) renders UserProfile as expected
  • (2) renders UserPosts as expected
  • (3) doesn't render UserProfile

note that (1) and (3) are 'exact' same routes but they don't render the same children components

you have to click (2) between (1) and (3) in order to make the bug reproducible

Most helpful comment

Quote from Evan in https://github.com/vuejs/vue-router/issues/608

I'd say this is expected behavior - named routes are precise targets, i.e. when you specify { name: 'parent' }, you are telling the router that you explicitly want to navigate to that route with no child route. If you want to navigate to the default child route, then you should be using the name of that child route instead.

So you need to just explicitly put names on default children.
However, as a work around if you don't want to do that, you can also explicitly redirect to default children: https://jsfiddle.net/fnlCtrl/7t69sp9x/
Anyway, you need to explicitly tell the router that you need it to always render the default children (instead of no children).

@HashemQolami It seems like a bug, would you like to open a new issue? Thanks!
As a quick workaround, add a trailing slash to your path:
<router-link to="/user/">/user (2) </router-link>

All 7 comments

I was about to file an issue, but found this relevant thread.

The point is, by using named routes (e.g. :to="{name: 'user', params: { id: 'foo'}}"), when the name property is set on the parent route, the '' empty child route's component is not rendered.

To be more clear, from the posted code by @nicolas-t :

const router = new VueRouter({
  routes: [
    { 
      path: '/user/:id', 
      name: 'user',              // name property is set on the parent route
      component: User,
      children: [
        { 
          path: '', 
          component: UserProfile // by using named routes,
                                 // this is not going to be rendered!
        },
        { 
          path: 'posts', 
          component: UserPosts
        }
      ]
    },

    {
      path: '', 
      component: Home,
    }
  ]
})

@HashemQolami

Out of curiosity, could you not just put name: 'user' on the first child (UserProfile)?

@nicolas-t

As mentioned to @HashemQolami , if you include the name attribute on the child routes, this works. The documentation doesn't really mention anything about using the name property on parent routes. I guess the way to look at it is that the parent route is more of a container, rather than page - therefore not really a "route" in it's own right, so no name required.

I updated your fiddle to give an example of what I mean.

@creativeesprit It produces another bug sorta.. which I was thinking of creating a new issue for that.

Consider the following snippet:

<router-link :to="{name: 'home'}" exact>Home</router-link>
<router-link to="/user">/user (2) </router-link>
<router-link :to="{name: 'user'}">user (named route) (3) </router-link>

<router-view></router-view>
const router = new VueRouter({
  mode: 'history',
  routes: [
    { 
      path: '/user', 
      component: User,
      children: [
        { 
          path: '',
          name: 'user',
          component: UserHome 
        }
      ]
    },
    {
      path: '',
      name: 'home',
      component: Home,
    }
  ]
});

Example here - click on the link (2), then click on the Home and finally click on the link (3).

Notice that the link (2) and link (3) are 'exact' same routes. But they both don't get the active-class at the same time if you click on the link (2).

However the active-class is added to both of them by clicking on the link (3).

That is because of the trailing slash / on the (3) link I guess which I do not know why that is so.

Quote from Evan in https://github.com/vuejs/vue-router/issues/608

I'd say this is expected behavior - named routes are precise targets, i.e. when you specify { name: 'parent' }, you are telling the router that you explicitly want to navigate to that route with no child route. If you want to navigate to the default child route, then you should be using the name of that child route instead.

So you need to just explicitly put names on default children.
However, as a work around if you don't want to do that, you can also explicitly redirect to default children: https://jsfiddle.net/fnlCtrl/7t69sp9x/
Anyway, you need to explicitly tell the router that you need it to always render the default children (instead of no children).

@HashemQolami It seems like a bug, would you like to open a new issue? Thanks!
As a quick workaround, add a trailing slash to your path:
<router-link to="/user/">/user (2) </router-link>

@fnlctrl For sure! Thanks.

Sorry, but this explanation doesn't make sense to me

Anyway, you need to explicitly tell the router that you need it to always render the default children (instead of no children).

Why call it a default child if it's not going to render by default unless I'm explicitly telling it to? Isn't that what I'm doing by configuring it as the default in the first place? I'm having a hard time accepting this "expected" behavior.

Was this page helpful?
0 / 5 - 0 ratings