Highlight active menu entry with Symfony UX Components

I was working on my sideproject and tried out Symfony UX Live Components. As I’m testing my code again to see if a list is working with components as intended I saw the highlighted menu item. That menu item wasn’t active so I asked myself if it is possible to achive this with Live Components.

In this blog-post I’m going to explain how to do this and my thoughts about this feature. I’ll not talk about setup symfony or talk about why every advancing developer should have a side-project or some “go-to” project ideas to test new technologies.

What are Live Components

Symfony UX Live Components provides reusable components that one can bind to an object. These components do not need any javascript to work.

It needs some practice to get used to it. I worked with the default examples of an alert message and was convinced I‘ll try to use it.

The default example didn‘t convice me at first so I worked with it a bit more. I created a list of users with it, which worked fine. I looked at my side project‘s menu and thought if it is possible to highlight the active menu without any javascript.

It may not be the most performant way to handle it but is a more advanced example for Syfmony UX Live Components.

Goal

I want to be able to click on a menu item, be redirected to this page and see a highlighted menu item so I know where I am.

I want to use no or as little Javascript as possible.

Get started

The file examples are centered around the components, that my project needs to enable the active menu and are not giving a working example project in the end. Nevertheless it may not require much to get it to work

Templates

Include the menu component in the file you would like your menu to be loaded

{# base.html.twig #}

...
    {% block menu %}
        {# Menu is loaded in a way that it can access the 'outer.' variables #}
        {% component('Menu') %}
        {% endcomponent %}
    {% endblock %}
...

Now the menu component with 2 example entries

{# templates/components/Menu.html.twig #}

{% set homeActive = outerScope.homeActive|default('') %}
{% set contractListActive = outerScope.contractListActive|default('') %}

<nav class="navbar navbar-expand-lg bg-body-secondary mb-2">
    <div class="container-fluid">
        <a class="navbar-brand" href="https://spacetraders.io">Spacetraders Implementation</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav nav-underline me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link {{ homeActive }}" aria-current="page" href="/">Home</a>
                </li>
                <li class="nav-item">
                    <a href="{{ path('contract.list') }}" class="nav-link {{ contractListActive }}">Contract List</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

This only provides the html part for the components, we need some php content now to get it to work.

// src/Twig/Components/Menu.php

namespace App\Twig\Components;

use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent]
class Menu
{
    public string $activeItemName = '';
}

This is our basic framework to enable our highlighting.

In a template it is used via

{# contracts/list.html.twig #}

{% extends 'base.html.twig' %}

{% block menu %}
    {% set contractListActive = 'active' %}
    {{ parent() }}
{% endblock  %}

How does it work now?

The magic happens with the in these lines

{# contracts/list.html.twig #}

{% set contractListActive = 'active' %}
{{ parent() }}

---------------------------------------------

{# templates/components/Menu.html.twig #}

{% set contractListActive = outerScope.contractListActive|default('') %}

I’m setting the contractListActive and am just calling parent() inside the menu block.
Inside the menu component did you notice the outerScope. in front of the variable name? This tells twig to look for a variable in the upper scope. More information about that in the syfmony ux documentation .
Now the variable is set to active and passed into the template to highlight the active menu.

I think this is a solution in case it is neccessary to create a higlighting feature without javascript or you may find some other useful cases for this.

Contact

For further questions or feedback
Mastodon: @florian25686@phpc.social
Github: florian25686
E-Mail: hello-blog at flexibledeveloper.eu