One of the problems I ran into in my Inertia & Laravel applications and saw other people do the same, was how to accurately determine the active route so you can style it accordingly.

In the PingCRM demo, we have a sidebar containing a menu whose items are highlighted every time you visit a specific route or a sub-route like “edit organization.”

Ping CRM active route

To check how that works, we open the MainMenu.vue file and see that we’re using an isUrl() method to check whether the menu item somewhat matches the current url path.

isUrl(...urls) {
  if (urls[0] === '') {
    return this.url === ''
  }

  return urls.filter(url => this.url.startsWith(url)).length
}

The problem is the current implementation only checks that the current url starts with whatever we pass in as an argument(s) – which is excellent for our demo. Still, it gets complicated when you want to check against longer and more dynamic urls, and you end up adding a bunch of other conditionals to make it work.

Ziggy to the rescue

A better solution would be to rely on route names. Ziggy already provides a route().current(name) method that checks whether the passed in name matches the current route.

We could replace the old isUrl(path) method with route().current(name) one and have 100% certainty that it will match the correct route.

<inertia-link :href="route('organizations')" 
  :class="route().current('organizations') ? 'text-white' : 'text-indigo-lighter'">
    Organizations
</inertia-link>

Highlight on multiple routes

If your application structure somehow requires you to highlight a menu item on entirely different routes, instead of adding a conditional, we can create an isRoute() method that can receive multiple routes as an argument.

You can add it as a vue mixin as it will most likely be used in all your application pages:

Vue.mixin({ 
  methods: { 
    route: window.route,
    isRoute(...routes) {
      return routes.some(route => this.route().current(route));
    }
  } 
})

This will allow us to check for multiple route names – in the example below we’re checking whether the current route is organizations or departments:

<inertia-link :href="route('organizations')"
  :class="isRoute('organizations', 'departments') ? 'text-white' : 'text-indigo-light'">
  Organizations
</inertia-link>

MainMenu reactivity

If your menu is in a layout like it is in PingCRM, it won’t be re-rendered because VueJS doesn’t update the component unless you specify a key that will change whenever we visit a new page.

Vue MainMenu component doesn’t re-render unless you specify a key

To fix that, we can set the current url as a key of the main-menu component.

<main-menu :key="url()" class="bg-indigo-darker..." />

Now, whenever the url() changes, the main menu component will re-render and highlight the correct route.