Vue-router: v-link-active only works on direct parent

Created on 19 Feb 2016  路  8Comments  路  Source: vuejs/vue-router

I'm trying to use the new v-link-active attribute and it only seems to work on the direct parent. I'd need to use it nested in a <li v-link-active><ul><li><a v-link="..."> scenario.

The documentation hints that this should work: "v-link will locate the closest parent element that has v-link-active and apply the active classes on that element instead."

Also, I have a use-case where multiple v-link-active would prove useful, e.g. <li v-link-active><ul><li v-link-active><a v-link="...">. Would be awesome if that would work as well.

need repro

Most helpful comment

In my opinion I would say it's quite fast since it knows where to go (any dom element has only one parent up to body). But it's my opinion, not the absolute truth ;)

I made a quick & easy fix, simply put : v-bind:class="{ 'active': hasRoute('/my/url') }" in my <template /> and the hasRoute simply do an indexOf between it's argument and the current url (from $router)

Works like a charm. Here's the code :

hasRoute: function (partial) {
    return (this.$route.path.indexOf(partial) > -1)
}

This let me place the active class anywhere I want.

All 8 comments

Same here.

It would be useful to keep a class on parent's parents. When you have nested routes the elements which link to parent route should have a supplementary class (v-link-active-trail) for instance. Would be useful...

More over, it would be interesting, in certain case, to work on multiple v-link-active (for example for nested sub-menus, when we need to select the current active element + show the parents, and parents element.

It would probably have performance issues then, because it needs to go all the way up to find v-link-active. No?

In my opinion I would say it's quite fast since it knows where to go (any dom element has only one parent up to body). But it's my opinion, not the absolute truth ;)

I made a quick & easy fix, simply put : v-bind:class="{ 'active': hasRoute('/my/url') }" in my <template /> and the hasRoute simply do an indexOf between it's argument and the current url (from $router)

Works like a charm. Here's the code :

hasRoute: function (partial) {
    return (this.$route.path.indexOf(partial) > -1)
}

This let me place the active class anywhere I want.

Cannot reproduce this, can you provide a jsfiddle?

Hmm let me guess - are you having something like this?

<li v-link-active>
  <ul>
    <li v-for="xxx" v-link="xxx">xxx</li>
  </ul>
</li>

@yyx990803 I guess so. Here is a working example.
https://jsfiddle.net/tejitak/o44z47ag/5/

Currently each link directive listens route change event and update the associated v-link-active element based on matching with the current route and the link value.
It does not work when multiple link directives have a same v-link-active parent because the updates triggered on last v-link directive overrides the v-link-active.

How about making either of the following changes?

  1. Just use nextTick for adding a v-link-active class (It's simple solution but not desirable)
  2. Listen route change event in v-link-active directive and check if one of v-link children is matched

Fixed in 3d12e95 (multiple v-link-active is now also supported)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alekbarszczewski picture alekbarszczewski  路  39Comments

liudangyi picture liudangyi  路  35Comments

sonic182 picture sonic182  路  32Comments

ifyio picture ifyio  路  31Comments

bmacnaughton picture bmacnaughton  路  30Comments