Ad

Timber Twig Add Class To Ancestor Menu Item When Page Is Not In Menu

- 1 answer

I have a menu with 2 sub-levels: /news/current-news/ - at the 'current-news' level, the top 'news' list item correctly picks up a 'current_page_parent' class. The items on that page are too many to put in as a 3rd level of menu, these are paginated teasers. When you click on one of those teasers, the url is /news/current-news/item-title - on that page I want the main 'news' item in the menu to still pick up a 'current_page_parent' class - is this possible since it's a child within the url, but not within the menu structure? My twig for the menu is:

{% if menu %}
<ul class="nav-main">
{% for item in menu.get_items %}
  <li class="nav-main-item{{ item.classes|join(' ') }}" role="menuitem"
  {% if item.children %}role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="0"{% endif %}>
    <a class="nav-main-link" target="_blank" rel="nofollow noreferrer" href="{{ item.get_link }}">{{ item.title }}</a>
    {% if item.get_children %}
      <ul class="nav-drop">
      {% for child in item.get_children %}
        <li class="nav-drop-item {{ child.classes | join(' ') }}">
          <a class="nav-drop-link" target="_blank" rel="nofollow noreferrer" href="{{ child.get_link }}">
            <div class="menu-item-title">{{ child.title }}</div> 
            <div class="menu-item-description">{{ child.post_content }}</div>
          </a>
        </li>
      {% endfor %}
      </ul>
    {% endif %}
  </li>
{% endfor %}</ul>{% endif %}

and from the page's php template:

<?php
/**
 * Template Name: Blog Landing Page
 * Template Post Type: page
 */

global $paged;
  if (!isset($paged) || !$paged){
      $paged = 1;
  }

 $context = Timber::context();

$timber_post     = new Timber\Post();
$context['post'] = $timber_post;

$newsArgs   =   array(
    'post_type'     =>  'post',
  'post_status'     => 'publish',
  'posts_per_page'  =>  6,
  'paged'           => $paged,
    'orderby'       =>  array(
    'date'          =>  'DESC'
));
$context['news'] = new Timber\PostQuery($newsArgs);

Timber::render( 'layouts/layout-blog.twig', $context );
Ad

Answer

I believe you can do this by comparing the post path and the menu item path. This example adds the current_page_parent class if the post path includes the menu item path:

{% if item.path in post.path %} current_page_parent {% endif %}

Here it is in your snippet:

{% if menu %}
<ul class="nav-main">
{% for item in menu.get_items %}
  <li class="nav-main-item{{ item.classes|join(' ') }}{% if item.path in post.path %} current_page_parent {% endif %}" role="menuitem"
  {% if item.children %}role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="0"{% endif %}>
    <a class="nav-main-link" target="_blank" rel="nofollow noreferrer" href="{{ item.get_link }}">{{ item.title }}</a>
    {% if item.get_children %}
      <ul class="nav-drop">
      {% for child in item.get_children %}
        <li class="nav-drop-item {{ child.classes | join(' ') }}">
          <a class="nav-drop-link" target="_blank" rel="nofollow noreferrer" href="{{ child.get_link }}">
            <div class="menu-item-title">{{ child.title }}</div> 
            <div class="menu-item-description">{{ child.post_content }}</div>
          </a>
        </li>
      {% endfor %}
      </ul>
    {% endif %}
  </li>
{% endfor %}</ul>{% endif %}

And if you want to limit that behavior to only the News menu item, just add another condition:

{% if item.title == 'News' and item.path in post.path %} current_page_parent {% endif %}
Ad
source: stackoverflow.com
Ad