Laravel: How to Make Menu Item Active by URL/Route

Founder of QuickAdminPanel
Probably one of the most common operation on every website is to assign “active” CSS class to the menu item which is currently opened. There are quite a few ways to detect that status, let’s review them.
We assume that the code will be based on Bootstrap and active menu item will have this:
<li> <a href="{{ route('admin.cities.index') }}"> <i class="fa fa-flag"></i> <span>Countries</span> </a> </li> <li class="active"> <a href="{{ route('admin.cities.index') }}"> <i class="fa fa-bank"></i> <span>Cities</span> </a> </li> <li> <a href="{{ route('admin.cities.index') }}"> <i class="fa fa-dollar"></i> <span>Currencies</span> </a> </li>
Now, the part that we’re interested in is class=”active”. In real Blade, it should be this:
<li class="{{ ($some_condition_if_active) ? 'active' : '' }}">
So, how to define that $some_condition_if_active?
Approach 1. Exact URL
Probably, the most simple one – you just check the exact URL and see if it matches:
<li class="{{ (request()->is('admin/cities')) ? 'active' : '' }}">
We use helper function $request->is().
Approach 2. Starting with the URL
This one is similar, but more flexible – will also match any other URL starting with the one we want, like /admin/cities/create or /admin/cities/1/edit.
We use asterisk (*) symbol for it.
<li class="{{ (request()->is('admin/cities*')) ? 'active' : '' }}">
Approach 3. Matching URL Segment
Another useful helper is to get URL segments by number.
<li class="{{ (request()->segment(2) == 'cities') ? 'active' : '' }}">
So, this one will match any URL like /admin/cities, /user/cities/edit etc.
Approach 4. Matching Route by Name
The one that I personally recommend. Route names is a really powerful weapon in case your URLs change for some reason. Let’s say we attached route names with this line in routes/web.php:
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function() { Route::resource('cities', 'Admin\CityController'); });
So we should match any route name like admin.cities.index or admin.cities.create for menu item to be active.
And here we use Route::getCurrentName() method.
<li class="{{ (strpos(Route::currentRouteName(), 'admin.cities') == 0) ? 'active' : '' }}">
In this case, all URLs assigned to our resourceful controller will be matched, like /admin/cities, /admin/cities/create, /admin/cities/1/edit etc.
Try our QuickAdminPanel generator!
18 Comments
Leave a Reply to Basyir Cancel reply
Recent Posts
Try our QuickAdminPanel Generator!
How it works:
1. Generate panel online
No coding required, you just choose menu items.
2. Download code & install locally
Install with simple "composer install" and "php artisan migrate".
3. Customize anything!
We give all the code, so you can change anything after download.
Hi Povilas, nice article you have here 🙂
I worked on a Pull Request last year to help developers regarding this matter.
You can check if the current route is active just with
Or even sub-routes (like editing, creating, or whatever with
If you prefer to use the route facade, you still can do that with
By using the * character, you can apply the active class to submenus easily:
`Route::named(..)` is not defined, should be `request()->route()->named(..)`.
Thanks Lloople!
Your comment is more useful than the post, thank you!
Hey Llope it helps but i’m getting error in url with parameters, for Ex;
Route::get(‘cms/{slug}’, ‘CmsController@cms’)->name(‘cms’);
routeIs(‘cms’,[‘policies’])) ? ‘active’ : ” }}”>policies
routeIs(‘cms’,[‘about’])) ? ‘active’ : ” }}”>About
it makes both routes active. Am i doing that right way.
I created a function routeIs
`if (!function_exists(‘routeIs’)) {
function routeIs($route, $return_ontrue, $return_onfalse)
{
return request()->routeIs($route) ? $return_ontrue : $return_onfalse;
}
}`
(strpos(Route::currentRouteName(), ‘admin.cities’) == 0)
should be
(strpos(Route::currentRouteName(), ‘admin.cities’) === 0)
Note the triple ‘=’ for strict equivalency
thank’s it’s really healpfull
Thanks!!!
How do you use helper Request in blade?
Not sure I understand your question.
Just use {{ request()->someOtherFunction() }}
I don’t like the given approaches! I would prefer to create a `sidebar.blade.php` and a `ViewComposerProvider` and a `SidebarViewComposer`. call the `SidebarViewComposer` via `ViewComposerProvider` boot function and pass the current controller and action. The making the decision. You can even make the logic in `SidebarViewComposer` and return one variable for each menu, contains ‘active’ or ”. Then place this variable inside the class of the menu,
I use this helper function.
for resource routes
// this will check users/index
if (!function_exists(‘set_active’)) {
function set_active($path)
{
$path = explode(‘.’, $path);
$segment = 1;
foreach($path as $p) {
if((request()->segment($segment) == $p) == false) {
return ”;
}
$segment++;
}
return ‘ active’;
}
}
What about active menu-open then active the links??
add “show” class to the parent.
{{ request()->routeIs(‘admin*’) ? ‘show’ : ” }}
You dazzle me everywhere. I search for Laravel for anything in it, and I find you in front of me. First, oh oh, I wish life revolved and studied from your paid courses. But the state in which I am, I cannot do anything except say, God willing.
I am trying to get the active class for the category.
Of course, the category is not always the same, so how can I use the values for this?
Suppose, URL is something like: localhost.com/category/{term}
Here the term is for any number or the name.
Great article, that inspire me to recreate my own navlink
View/components/SideNavLink.php
class SideNavLink extends Component
{
public $link;
/**
* Create a new component instance.
*
* @return void
*/
public function __construct($link)
{
$this->link = $link;
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view(‘components.side-nav-link’);
}
and in side-nav-link.blade.php
{{$slot}}
and in our pages just use
Stock
maybe this is too long but components can be reused and only need one simple code used