add active class to link with sf2 and twig
Solution 1
Twig allows for conditionals and the Request object is available throughout the application. If you are including the template, to get the route you want to use:
app.request.attributes.get('_route')
If you are using the render function, you want to use:
app.request.attributes.get('_internal')
With that, you should be able to use:
class="{% if app.request.attributes.get('_route') == '_list' %}active{% endif %}"
or shorter:
class="{{ app.request.get('_route') == '_list' ? 'active' }}"
Solution 2
Sometimes you don't want to do exact matching of a route. For those cases, you can use the "starts with" conditional logic of twig.
As an example, lets assume you are working with books. You have the following routes: book, book_show, book_new, book_edit. You want the navigation item Book to be highlighted for any of those cases. This code would accomplish that.
<a class="{% if app.request.attributes.get('_route') starts with 'book' %}active{% endif %}">Books</a>
<a class="{% if app.request.attributes.get('_route') starts with 'author' %}active{% endif %}">Authors</a>
This example works with at least Symfony 2.3.x
Solution 3
Shortest version:
{% set route = app.request.get('_route') %}
<li class="{{ route starts with 'post' ? 'open' }}"></li>
<li class="{{ route starts with 'category' ? 'open' }}"></li>
Sometimes useful:
{% set route = app.request.get('_route') %}
<li class="{{ 'post' in route ? 'open' }}"></li>
<li class="{{ 'category' in route ? 'open' }}"></li>
Solution 4
With ternary operator:
{% set route = app.request.attributes.get('_route') %}
<ul class="nav navbar-nav">
<li {{ route == 'profile_index' ? 'class="active"' }}><a href="{{ path('profile_index') }}"><i class="icon-profile position-left"></i> My Profile</a></li>
<li {{ route == 'influencers_index' ? 'class="active"'}}><a href="{{ path('influencers_index') }}"><i class="icon-crown position-left"></i> Influencers</a></li>
<li {{ route == 'task_manager_index' ? 'class="active"'}}><a href="{{ path('task_manager_index') }}"><i class="icon-alarm-check position-left"></i> Task Manager</a></li>
</ul>
Solution 5
This is done with symfony 3.4, but probably something similar can be done with SF2.
src\AppBundle\Twig\AppExtension.php
<?php
namespace AppBundle\Twig;
use Symfony\Component\HttpFoundation\RequestStack;
class AppExtension extends \Twig_Extension
{
private $requestStack;
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('activeMenu', [$this, 'activeMenu'])
];
}
/**
* Pass route names. If one of route names matches current route, this function returns
* 'active'
* @param array $routesToCheck
* @return string
*/
public function activeMenu(array $routesToCheck)
{
$currentRoute = $this->requestStack->getCurrentRequest()->get('_route');
foreach ($routesToCheck as $routeToCheck) {
if ($routeToCheck == $currentRoute) {
return 'active';
}
}
return '';
}
}
Add this to services.yml
services:
#... some other services
AppBundle\Twig\AppExtension:
arguments: ["@request_stack"]
Usage:
<ul class="nav navbar-nav">
<li class="{{ activeMenu(['form', 'edit_form']) }}"><a href="{{ path('form') }}">Form</a></li>
<li class="{{ activeMenu(['list']) }}"><a href="{{ path('list') }}">List</a></li>
</ul>
choise
Updated on February 17, 2020Comments
-
choise about 4 years
following simple code:
<li><a href="{{ path('_list') }}">List</a></li>
is there a simple way to add an
class="active"
if the current page matches the_list
route?using the newest PR-Release of symfony2 and twig as template engine