VueJS 3 - Issue with applying the <router-link-active> class to routes that share the same path starting name

In my navigation bar, I have created 3 links which are all declared at the root level of the router object. I've applied some simple styling to highlight the active link on the navbar using the <router-link-active> class. Everything works as expected - switching between links updates the URL, changes the <router-view>, and applies the correct style to the currently active navbar link.

The issue arises when I click on a 4th link that is also declared at the root level of the router object, starting with the same path name as the currently active link. This causes the <router-link-active> class to behave unexpectedly.

{ path: "/link2", component: link2 },
{ path: "/link2/sibling", component: sibling },

My understanding is that because the path /link2/sibling starts with the same name as /link2, the navbar item that navigates to /link2 should still have the <router-link-active> class even when /link2/sibling is the active URL.

Check out the Codesandbox for reference

App.vue

<template>
  <div>
    <ul class="flex gap-x-5">
      <router-link to="/">
        <li>Link 1</li>
      </router-link>
      <router-link to="/link2">
        <li>Link 2</li>
      </router-link>
      <router-link to="/link3">
        <li>Link 3</li>
      </router-link>
    </ul>
  </div>
  <router-view />
</template>

<script>
export default {
  name: "App",
};
</script>

<style>
a:hover,
a:active,
a.router-link-active {
  color: #f1a80a;
  border-color: #f1a80a;
  background-color: #1a037e;
}
</style>

main.js

import App from "./App.vue";
import router from "./router.js";

const app = createApp(App);

app.use(router);

app.mount("#app");

router.js

import { createRouter, createWebHistory } from "vue-router";
import link1 from "./components/link1.vue";
import link2 from "./components/link2.vue";
import sibling from "./components/sibling.vue";
import link3 from "./components/link3.vue";

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: "/", component: link1 },
    { path: "/link2", component: link2 },
    { path: "/link2/sibling", component: sibling },
    { path: "/link3", component: link3 }
  ]
});

export default router;

link1.vue

<template>
  <div>You are inside Link1</div>
</template>

link2.vue

<template>
  <div>
    <router-link to="/link2/sibling">
      You are inside Link 2 (CLICK ME)
    </router-link>
  </div>
</template>

link3.vue

<template>
  <div>You are inside Link 3</div>
</template>

sibling.vue

<template>
  <div>You are inside Link2 sibling</div>
</template>

Answer №1

It is common for routing behavior to behave in this way. When you click on You are inside Link 2 (CLICK ME) within the link2.vue component, the vue-router will load sibling.vue in the router-view section of your App.vue. As a result, the link You are inside Link 2 (CLICK ME) is not present in that view to display the router-link-active styles. To see these styles, it is necessary to ensure that the link remains visible in the view and does not get hidden by the vue-router.

To achieve this, you can utilize Nested Routes in vue-router as shown below. First, modify your router.js file with the following changes:

import { createRouter, createWebHistory } from "vue-router";
import link1 from "./components/link1.vue";
import link2 from "./components/link2.vue";
import sibling from "./components/sibling.vue";
import link3 from "./components/link3.vue";

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: "/", component: link1 },
    { 
        path: "/link2",
        component: link2,
        children: [
            {
              path: 'sibling',
              component: sibling
            },
          ]
    },
//    { path: "/link2/sibling", component: sibling
//        
//    },
    { path: "/link3", component: link3 }
  ]
});

export default router;

Next, add a <router-view> to your link2.vue file like this:

<template>
  <div>
    <router-link to="/link2/sibling">
      You are inside Link 2 (CLICK ME)
    </router-link>
    <router-view></router-view>
  </div>
</template>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Destructuring and For of Loop in ES6: Capturing the first object only

Working with my react app, I have a specific object called 'topics' that I am looping through: const topics = [ {name: 'Mon', color: 'blue', id: 1}, {name: 'Tue', color: 'red', id: 2}, {name: 'W ...

Node - ensure that each API call finishes before initiating the next one

Currently, I am encountering an issue with my POST request within the 'add-users' route. I have initialized an array named success and aim to trigger the next API call once a response is received. It seems that the problem lies in sending too ma ...

Bring in the content to Notepad utilizing jQuery

How can I export data to Notepad? I have fields for Name, Age, and WorkingStatus that are input as text and textarea. Is there a demo or code available to help me insert this data into Notepad? ...

How to interact with a C# List using JavaScript

Our internship project entails creating a business application using Unity WebGL. However, we're facing a challenge when it comes to retrieving a list from C# to populate a Select element on our webpage. We've successfully communicated and retrie ...

How to disable annoying browser ad extensions using Javascript

Is there a way to prevent browser add-ons from injecting HTML code? My website built in angularjs is experiencing routing issues due to certain browser add-ons. The following HTML snippet is causing errors in my angularjs: <script async="" src="http:/ ...

Having trouble finishing the npm installation process

Having trouble with completing 'npm install'. Can someone please assist me?</p> <pre><code>Encountering a warning about an old lockfile while running npm install. The package-lock.json file was created with an outdated version o ...

Difficulty with AngularJs Translation Partials

I have encountered an issue with binding translation. Some objects are converting to their translated value successfully, while others, as mentioned below, are not working. This problem only occurs the first time I build the project. Upon refreshing, every ...

Add a click event to elements that match

I must admit that I am not particularly knowledgeable in Javascript/jQuery and my question might come across as trivial. However, I am trying to assign a click event to every element on the page with the following code: $(document).ready(function () { ...

Choose an image in Vue.js if it is available

As a professional working with multiple companies using the same portals and webpages, I am looking for a way to dynamically set the home icon to display each company's logo if provided, or default to mdi-home if not. Instead of using a long list of I ...

Which type of element does Youtube utilize for the videos on its own domain - <iframe> or <video>?

Do they have a different method for incorporating their videos? My goal is to utilize the playbackRate property on a non-embedded YouTube video for a Chrome extension. ...

Issue: function is not a valid type (during mount)

Currently, I'm trying to add a feature that automatically closes all menus and modals when a user clicks outside of the specified area. Although I am successfully calling this.closeMenu(), an error is occurring stating that this.closeMenu is not reco ...

Tips on moving information from one form to another after referencing the original page using Javascript and HTML

Imagine this scenario: A page with three text fields, each with default values. There is also a hyperlink that performs a database lookup and returns parameters to the same page where the hyperlink was clicked. The goal is for the text boxes to be automa ...

Trouble with executing two asynchronous AJAX calls simultaneously in ASP.NET using jQuery

When developing a web application in asp.net, I encountered an issue with using jQuery Ajax for some pages. The problem arose when making two asynchronous Ajax calls - instead of receiving the results one by one, they both appeared simultaneously after the ...

Utilizing Nuxt Compostion API to Swap Classes on Hover

<script setup> import Logo from "../assets/svgs/Logo"; import Menu from "../assets/svgs/Menu"; const hover = Boolean let boxTop if (hover === true) { boxTop = 'boxTop--0' } else { boxTop = 'boxTop--20' } ...

What is the best way to use ajax for uploading multiple images at once?

I'm having trouble uploading multiple image files. Can someone please review my code? <form id="fileupload" method="POST" enctype="multipart/form-data"> <input type="file" name="files[]" multiple="multiple" id="images_input"> & ...

Unable to view Bootstrap Icons in Gulp 4

I recently integrated the new bootstrap icons npm package into my project using Gulp 4, the latest version. Everything was installed successfully and was working smoothly. However, I encountered an issue when trying to declare the icon in my index.html fi ...

Can a Typescript class type be defined without explicitly creating a JavaScript class?

I am exploring the idea of creating a specific class type for classes that possess certain properties. For example: class Cat { name = 'cat'; } class Dog { name = 'dog'; } type Animal = ???; function foo(AnimalClass: Animal) { ...

The returned error object from express does not include the error message

I recently posted a question related to an error issue. I am now wondering if I should have edited that question instead. Regarding the code snippet below: app.use((err, req, res, next) => { res.status(err.status || 500); res.json({ message: e ...

Include a class in ul > li elements upon page load in Angular4

I attempted to add a class to each "li" element in an Angular4 page, but the class was not applied. Here is the relevant HTML code: <ul class="pagination"> <button class="previous" (click)="previous()">Previous</button> <button ...

Does TypeGraphQl have the capability to automatically format SQL queries?

I am utilizing TypeORM in conjunction with TypeGraphQL. I am curious about the SQL query result that TypeGraphQL provides. For instance, if I have a User Table with numerous columns and a simple resolver like this: @Resolver() class UserResolver { @Q ...