How to make a component with menu item changing css to active when clicked

Could not find solution how to make menu item active. I read everything on vue documentation and I tried to bind class and whatnot. It works if I use example provided in documentation. But my files are organized a little bit different. Here is how I call it:
Navigation.vue file

<template>
        <div class="breadcrumbs">
            <div class="inner">
                <ul class="cf">
                    <li>
                        <a v-on:click="setActive()" :class="{ active:isActive }">
                            <span>1</span>
                            <span>About me {{isActive}}</span>
                        </a>
                    </li>
                    <li>
                        <a v-on:click="setActive('resume')" :class="{ active:isActive }">
                            <span>2</span>
                            <span>Resume</span>
                        </a>
                    </li>
                    <li>
                        <a v-on:click="setActive('skills')" :class="{ active:isActive }">
                            <span>3</span>
                            <span>Skills {{ isActive }}</span>
                        </a>
                    </li>
                    <li>
                        <a v-on:click="setActive('contact')"  :class="{ active:isActive }">
                            <span>4</span>
                            <span>Contact</span>
                        </a>
                    </li>
                </ul>
            </div>
        </div>
    </template>
    <script>
        export default{
            props: [
                'source',
                'title'
            ],
            data() {
                return {
                    isActive: false
                }
            },
            computed: {
                 activeClass: function(){
                    return this.$data.isActive ? 'active' : '';
                 }
            },
            methods: {
                setActive(){
                    // vm = this;
                    Vue.set(this.$data, 'isActive', true)
                }
            },
            mounted(){
                console.log('Component ready.')
            }
        }
    </script>

and app.js

Vue.component('navigation', require('./components/Navigation.vue'));

const app = new Vue({
    el: '#app'
});

Thanks

Well, you have one Boolean value, isActive. And nothing that tells Vue for which menu item this should be used.
Also, you define the classname in your class binding (:class="{active: ....}") and then you return it in the computed prop - but the computed prop should return a boolean. Which make it unnessessary because isActive is already boolen.

So you might see how this cannot work.

  • Instead of a boolean value, you should set a different string value for each menu item.
  • Instead of the computed prop, add another method that can take an argument to check weither item is active
<template>
  <a v-on:click="setActive('about')" :class="{ active: isActive('about') }">

  <a v-on:click="setActive('resume')" :class="{ active:isActive('resume') }">
  <!-- and so on. -->
</template>

<script>
export default {
  data() {
    return { activeItem: 'about' }
  },
  methods: {
    isActive: function (menuItem) {
      return this.activeItem === menuItem
    },
    setActive: function (menuItem) {
      this.activeItem = menuItem // no need for Vue.set()
    }
  }
}
</script>
6 Likes

Thank you!
You are right, and I see where I made mistake. Thank you for your help, works perfectly !

I thought I chime in because I was also looking for a solution and solved it merely with a little CSS. When using Vue’s router link, the correct anchor with href will be generated for you like so (assuming that you have named routes):

<nav>
    <router-link :to="{ name: 'home' }">Home</router-link>
</nav>

Vue even assigns the .router-link-exact-active and .router-link-active classes for you on click, so this little snipped of styling will do the trick:

nav a.router-link-active {
    font-weight: 700; // Bolds the text.
}
7 Likes

That was the easiest solution ever!! Thanks much!

Here another solution:
Let have to links like this:

< a href="/manage" v-bind:class="{‘bg-gray-600’:url_current==’/manage/dashboard’ }" class=" px-3 py-2 rounded-md text-sm text-white focus:outline-none focus:text-white focus:bg-gray-700">Dashboard< /a>

< a href="/manage/user" v-bind:class="{‘bg-gray-600’:url_current==’/manage/user’ }" class=“ml-4 px-3 py-2 rounded-md md:text-sm lg:text-lg text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700”>Users< /a>

Then just make a computed variable like this:

computed:{

  •             url_current: function(){*
    
  •                      return window.location.pathname***
    
  •            }*
    

},

That all!!!