Skip to content

children named routes and empty path not rerendering #822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nicolas-t opened this issue Oct 22, 2016 · 10 comments
Closed

children named routes and empty path not rerendering #822

nicolas-t opened this issue Oct 22, 2016 · 10 comments

Comments

@nicolas-t
Copy link

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

@theshem
Copy link

theshem commented Oct 23, 2016

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,
    }
  ]
})

@creativeesprit
Copy link

@HashemQolami

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

@creativeesprit
Copy link

@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.

@theshem
Copy link

theshem commented Oct 23, 2016

@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.

@fnlctrl
Copy link
Member

fnlctrl commented Oct 24, 2016

Quote from Evan in #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 fnlctrl closed this as completed Oct 24, 2016
@theshem
Copy link

theshem commented Oct 24, 2016

@fnlctrl For sure! Thanks.

@joemsak
Copy link

joemsak commented Apr 8, 2018

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.

@nicolaskopp
Copy link

nicolaskopp commented Jun 14, 2021

Completely agree with @joemsak . Just seems like counter-intuitive routing behaviour.

If I point a route to a component, and I have a child route with no parameters, this child route should automatically be triggered when the parent route is called without parameters, but it's not. It have to explicitly tell the router: "Render this child component".

Why use a router in a first place when it does not route.

Edit: Consider the following code. This does NOT work:

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    redirect: { name: "Books" },
  },
  {
    path: "/books",
    component: Books,
    name: "Books",
    children: [
      {
        path: "",
        name: "BookList",
        component: BookList,
      },

this would work:

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    redirect: "/books",
  },
  {
    path: "/books",
    component: Books,
    children: [
      {
        path: "",
        name: "BookList",
        component: BookList,
      },

I have no idea why named routes behave differently in this case. Cannot wrap my head around it.

@lobo-tuerto
Copy link

It's easy to make it work with name routes.
If you want Books to open the BookList child, then just add another redirect like this:

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    redirect: { name: "Books" },
  },
  {
    path: "/books",
    component: Books,
    name: "Books",
    redirect: { name: "BookList" },
    children: [
      {
        path: "",
        name: "BookList",
        component: BookList,
      },

@doorahmie
Copy link

I think that using 'redirect' to go to default children is an inappropriate naming. It's unnatural.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants