1

I have a navbar at the bottom of my page which is in the App.vue component so that it sits on top of every page. What I would like to happen is that when a user navigates to a page, this page's button in the navbar highlights/changes class.

I am using composition API, but thought their may be a way of doing this in HTML without having to write in the script.

I can't seem to find a best practice online, please can someone help?. This was my attempt but it doesn't work. There must be a simpler way! Thank you.

HTML:

 <ul class="navbar-nav flex-row justify-content-center">
            <li class="nav-item px-2">
                <router-link to="/" class="nav-link"><i class="fa-solid fa-house" :class="{'text-primary': currentRouteId === 1, 'text-muted': currentRouteId != 1}"></i></router-link>
            </li>
            <li class="nav-item px-2">
                <router-link :to="{ name: 'Rooms' }" class="nav-link"><i class="fa-solid fa-square" :class="{'text-primary': currentRouteId === 2, 'text-muted': currentRouteId != 2}"></i></router-link>
            </li>
            <li class="nav-item px-2">
                <router-link :to="{ name: 'Rooms' }" class="nav-link"><i class="fa-solid fa-video" :class="{'text-primary': currentRouteId ===3, 'text-muted': currentRouteId != 3}"></i></router-link>
            </li>
            <li class="nav-item px-2">
                <router-link :to="{ name: 'Rooms' }" class="nav-link"><i class="fa-solid fa-shield" :class="{'text-primary': currentRouteId === 4, 'text-muted': currentRouteId != 4}"></i></router-link>
            </li>
            <li class="nav-item px-2">
                <router-link :to="{ name: 'Rooms' }" class="nav-link"><i class="fa-solid fa-door-closed" :class="{'text-primary': currentRouteId === 5, 'text-muted': currentRouteId != 5}"></i></router-link>
            </li>
        </ul>

Script:

<script>
import { computed, ref, onUpdated } from 'vue'
import { useStore } from 'vuex'
import { useRoute } from 'vue-router'

export default {

  setup(){
    const store = useStore()
    const route = useRoute()
    const pageParams = computed(() => store.state.pageParams)

    const currentRouteName = computed(() => route.name)
    var currentRouteId = ref(null)

    //
    onUpdated(() => {
      if(currentRouteName.value === 'Home'){console.log('Home'); currentRouteId=1;}
      if(currentRouteName.value === 'Rooms' || currentRouteName.value === 'Room'){console.log('Rooms'); currentRouteId=2;}
      if(currentRouteName.value === 'CCTV'){console.log('CCTV'); currentRouteId=3;}
      if(currentRouteName.value === 'Security'){console.log('Security'); currentRouteId=4;}
      if(currentRouteName.value === 'Door Entry'){console.log('Door Entry'); currentRouteId=5;}

      console.log(currentRouteId)
    })


    return { pageParams, currentRouteName, currentRouteId }
  },
}

</script>

2 Answers 2

3

Why not use the active-class prop of RouterLink? Then you can use whatever Bootstrap class you want to make it appear highlighted (ie: active, border-dark, etc..)

   <ul class="navbar-nav flex-row justify-content-center">
           <li class="nav-item px-2">
                <router-link to="/" class="nav-link" active-class="active border border-dark"><i class="fa-solid fa fa-home"></i></router-link>
           </li>
           <li class="nav-item px-2">
                <router-link :to="{ name: 'Rooms' }" active-class="active border border-dark" class="nav-link"><i class="fa fa-solid fa-square"></i></router-link>
           </li>
           <li class="nav-item px-2">
                <router-link :to="{ name: 'More' }" active-class="active border border-dark" class="nav-link"><i class="fa fa-solid fa-shield"></i></router-link>
           </li>
   </ul>

Vue 3 Demo

and if all links will use the same active class you can just set it in the router config...

const router = createRouter({
    history,
    routes,
    linkExactActiveClass: 'active',
})
Sign up to request clarification or add additional context in comments.

Comments

0

This is a similar issue that I had awhile ago. The solution is similar to what you already have. The change I would make is moving the routes down into your data and v-forring that array you made down there. Then, I would create a wrapper component around the components. Inside the new wrapper component, I would just set up a computed watcher, then if(route.name === prop.name) return "class" I can whip up a quick sandbox for you to look at how I would do it. Though, I figure you can probably get it on your own. It's just making a quick wrapper component to watch the route change and adjusting the class accordingly. Alternatively, and probably a better option would be to possibly use CSS :active on the class. I believe router-link has active-class prop, which you might be able to add a custom class for being active. But, I'm not sure if that's meaning that it's CSS "active" or being active as in it is the current route. (Css would be "active" while it's actively being clicked, then disappear after the event)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.