Menus

In Timber, you can use Timber\Menu to make a standard WordPress menu available to the Twig template as an object you can loop through.

Once the menu becomes available to the context, you can get items from it in a way that is a little smoother and more versatile than WordPress’s wp_nav_menu() function. (And you never again need to rely on a crazy Walker Function).

Initializing a menu

Timber\Menu can be initialized with different values:

You can pass the slug of the menu you want to use:

$menu = new Timber\Menu( 'site-tools' );

Or the ID number of the menu:

$menu = new Timber\Menu( 3 );

Or the proper name from the admin:

$menu = new Timber\Menu( 'Primary Navigation' );

Or the slug of the registered location:

$menu = new Timber\Menu( 'primary' );

Or pass nothing. This is good if you have only one menu. In that case Timber will just grab what you got.

$menu = new Timber\Menu();

Options

Optionally, you can send additional options to Timber\Menu. Current only depth is supported (see https://developer.wordpress.org/reference/functions/wp_nav_menu/ for reference)

$args = array(
	'depth' => 2,
);
$menu = new Timber\Menu( 'primary', $args );

Setting up a menu globally

The first thing to do is to initialize your menu using Timber\Menu. This will make the menu available as an object to work with in the context. Because we need the menu on every page, we can add it to the global context through the timber/context filter:

functions.php

<?php

add_filter( 'timber/context', 'add_to_context' );

function add_to_context( $context ) {
    // So here you are adding data to Timber's context object, i.e...
    $context['foo'] = 'I am some other typical value set in your functions.php file, unrelated to the menu';

    // Now, in similar fashion, you add a Timber Menu and send it along to the context.
    $context['menu'] = new \Timber\Menu( 'primary-menu' );

    return $context;
}

Now, when you call Timber::get_context(), your menu will already be set in the context. You don’t need to initialize the menu in all your template files.

index.php

<?php

$context = Timber::get_context();

Timber::render( 'index.twig', $context );

Displaying the menu items

In your Twig file, you can loop over the menu items like normal arrays. You’re in complete control of the markup.

index.twig

<nav>
    <ul class="nav-main">
        {% for item in menu.items %}
            <li class="nav-main-item {{ item.classes|join(' ') }}">
                <a class="nav-main-link" href="{{ item.link }}">{{ item.title }}</a>
                {% if item.children %}
                    <ul class="nav-drop">
                        {% for child in item.children %}
                            <li class="nav-drop-item">
                                <a href="{{ child.link }}">{{ child.title }}</a>
                            </li>
                        {% endfor %}
                    </ul>
                {% endif %}
            </li>
        {% endfor %}
    </ul>
</nav>

The current menu item

When you need to check whether a menu item is the current menu item, you can use the current property. Here’s an example to display child menu items only if it’s the menu item is the currently visited page:

Twig

{% if item.current and item.children %}
    <ul class="nav-child">
        {% for child in item.children %}
            <li class="nav-child-item">
                <a class="nav-child-link" href="{{ child.link }}">{{ child.title }}</a>
            </li>
        {% endfor %}
    </ul>
{% endif %}

Other properties that are available are current_item_parent for direct parents of a menu item and current_item_ancestor for when you have deeper nesting.

Tips