My Q is equal as Remove link from active page in menu

I need the active page in my menu not to be a link.

So let's say I'm on the services page, I need my menu structure to look like this:

<ul class="menu">
    <li class="first leaf"><a href="/mysite/">home</a></li>
    <li class="leaf">services</li>
    <li class="leaf"><a href="/mysite/portfolio">portfolio</a></li>
    <li class="leaf"><a href="/mysite/contact">contact</a></li>
</ul>

How can I do that in drupal 8?

Update what about this thing in my theme menu--main.html.twig?

{% if item.attributes.hasClass('active') %}
<span>{{ item.title }}</span>
{%- else -%}
{{ link(item.title, item.url) }}
{%- endif -%}

In D8 the handling of active links is split between php and js, so that the menus can be cached independently from the page they appear on. A solution in php or twig is only possible, if you switch of the caching of menus, but this is not good for performance. So a better approach is probably in javascript.

Remove the link tag by selecting the links with the class is-active:

mytheme/js/remove-active-links.js

(function ($, Drupal) {

  'use strict';

  Drupal.behaviors.removeActiveLinks = {
    attach: function (context) {

      $(context).find('a.is-active').contents().unwrap();

    }
  };

})(jQuery, Drupal);

You need to define a dependency on the core active-link.js, which sets the class is-active, so that your js file runs later:

mytheme/mytheme.libraries.yml

remove-active-links:
  version: 1.x
  js:
    js/remove-active-links.js: { }
  dependencies:
    - core/jquery
    - core/drupal
    - core/drupal.active-link

Background information

This is the most basic solution. It loads jQuery also for anonymous traffic. If you already use it, this is not a problem. If you want to avoid jQuery you have to look at ActiveLinkResponseFilter. This response subscriber adds the class is-active for anonymous requests. Add a custom response subscriber with a lower priority that checks for this class and removes the link tag similar to the js code. In this case load the js library only for authenticated requests.

  • Thanks! but I think it's not good solution for SEO? – wakh.ru Apr 28 '17 at 14:26
  • Don't think that's bad for SEO, but it doesn't matter, because googlebot crawls javascript for about 2 or 3 years now. And I think as drupal goes ahead with optimizing menu caching strategy with javascript it's best to follow the same path. – 4k4 Apr 28 '17 at 14:45
  • you are right and your solution working so thank you again! – wakh.ru Apr 28 '17 at 14:50
  • What do you think about my update? – wakh.ru Apr 28 '17 at 22:52
  • The class active is for the active trail, not for the active link. I put some background information in the answer for a php solution. – 4k4 Apr 29 '17 at 8:02

The HTML is generated by a twig template, you should see {% for item in items %} in one of your theme's menu templates, and then do a condition e.g. {% if item.in_active_trail %}. You could probably just check for item.in_active_trail in the item variable, but if that's not good enough, just use Kint (from the devel module) to figure out a variable that works for your situation.

  • My theme is "businessgroup zymphonies theme" and in links.html.twig i found this <ul{{ attributes }}> {%- for key, item in links -%} <li{{ item.attributes.addClass(key|clean_class) }}> {%- if item.link -%} {{ item.link }} {%- elseif item.text_attributes -%} <span{{ item.text_attributes }}>{{ item.text }}</span> {%- else -%} {{ item.text }} {%- endif -%} </li> {%- endfor -%} </ul> – wakh.ru Apr 27 '17 at 20:23
  • This is probably only something that theme maintainer can solution, then. – Kevin Apr 27 '17 at 23:46

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.