Get a Fieldable Drupal Menu: Menu Item Extras Overview

Menu Item Extras Overview

Why do the Menus in the Drupal 8 release still not have fields when we have so many modules in Drupal 7 that help us build mega menus? We asked this question ourselves when faced with complex menus in our projects

We did deep research into menu implementation in Drupal 8, and, surprisingly, menu items in Drupal 8 are entities, and any entities in Drupal 8 could have fields. But the existing modules and the Drupal core do not use it to add fields. Modules usually use additional entity type or menu item attributes to store data from attached fields.  

Menu%20Item%20Extras%20overview-01.svg

Menu Item Extras background

As we found out, the Drupal core has a weak and inflexible implementation of the Menu Link Content entity type. Core services for menus were too big and complex and bundle hardcoded, provided no integration with other modules, and lacked template suggestions. That was an epic issue, so we decided to fix it and develop a new Drupal module.

We didn’t want just to add fields for menu items. We wanted to give website admins and developers a useful module with an intuitive administration interface and clear code. We aimed to deliver to the Drupal community a high-quality module to demonstrate how powerful Drupal 8 is.

Before the development of each new feature, we had long meetings and discussions with our team of one front-end and three back-end developers. After 3 weeks of development, we released the Menu Item Extras module, which has been downloaded 100,000+ times already as of January 2019.

How it works

Menu Item Extras makes the Menu Link Content entity fully fieldable. The module fixes core issues and provides a couple features, like Demo Module and View mode per menu item, which makes developers' lives easier. It allows us to use all fields types for menus as for the normal Drupal 8 entity. Each menu is a bundle for the Menu Link Content.

The core bundle is hardcoded to `menu_link_content`

Drupal\menu_link_content\Entity\MenuLinkContent::preCreate


/**
   * {@inheritdoc}
   */
  public static function preCreate(EntityStorageInterface $storage, array $values) {
    $values += ['bundle' => 'menu_link_content'];
  }

To avoid changing the menu item bundle, the module blocks the ability to set a parent link from other menus. So, in the Parent Link field, you will see links from the current menu only (see menu_item_extras_form_menu_link_content_form_alter). However, we’re not sure if anyone uses it at all.

Demo module

This module has a submodule `mie_demo_base` for a demonstration of base features. There, you can find a new menu “Menu Item Extras Demo Menu” with added fields and overridden templates.

Welcome%20to%20Site%20Install%20%20%20Site%20Install.jpg

View mode per menu item

Each menu item has a new field called “View mode.” For each menu item, you can set a specific view mode (e.g., teaser, banner, etc.). This field is available when you add at least one field to the menu.

Menu%20Item%20Extras%20overview_2.6.jpg

You can add view modes for Menus from the default page with view modes for all entity types.

Menu%20Item%20Extras%20overview_2.4.jpg

Menu Item Extras provides an additional overview page with a list of all menu items and their view modes.

Menu%20Item%20Extras%20overview_2.2.jpg

Since each menu item could have child items, the module provides an extra field “Children” on the manage display.
Menu%20Item%20Extras%20overview_2.3.jpg

Views integration

Since we have a normal Drupal entity for the menu items, we can use it via views. By default, the core Menu Link Content entity type doesn’t work with views. Menu Item Extras fixes this issue as well (see menu_item_extras_entity_type_build).

Menu%20Item%20Extras%20overview_2.5.jpg

One of the use cases is the active menu item content in a separate region. To implement this, you have to use a contextual filter with Entity ID and default value type “Active menu item ID,” which is also provided by this module.
Menu%20Item%20Extras%20overview_2.1_0.jpg

Now we can place our views block in the region and see what we get.
Menu-Item-Extras-overview_2.jpg

Menu template suggestions

Menu Item Extras extends template suggestions for the menus. Here, you can check suggestions for the Main menu in the Primary menu region:

<!-- FILE NAME SUGGESTIONS:

  * menu--extras--main--primary-menu.html.twig - region related (extra)
  * menu--extras--main.html.twig - menu name related(extra)
  x menu--extras.html.twig - default template from the module(extra)
  * menu--main.html.twig - global template
  * menu.html.twig - global template

-->

Inside the menu template, we render menu items levels and add suggestions for each level starting with 1; the main level with ID 0 is skipped:

<!-- FILE NAME SUGGESTIONS:
  * menu-levels--main--level-1.html.twig
  * menu-levels--main.html.twig
  x menu-levels--level-1.html.twig
  * menu-levels.html.twig
-->

Inside the menu level, we render the Menu Link Content entity with all added fields. This is a new theme. It renders only the entity with fields but without menu item links.

<!-- FILE NAME SUGGESTIONS:

 * menu-link-content--main--standard.front-page--default.html.twig
  * menu-link-content--main--standard.front-page.html.twig
  * menu-link-content--main--menu-level-0--default.html.twig
  * menu-link-content--main--menu-level-0.html.twig
  * menu-link-content--menu-level-0.html.twig
  * menu-link-content--main--default.html.twig
  * menu-link-content--main.html.twig
  * menu-link-content--default.html.twig
  x menu-link-content.html.twig

-->

Since the Drupal menu system uses recursion to render children, inside the menu-link-content.html.twig we have menu-levels.html.twig, and it repeats until the last child.

This is an illustration of the hierarchy of templates and how they are rendered.

Menu%20Item%20Extras.svg

Inside the menu-link-content.html.twig, we have an additional variable show_item_link. This variable is used to render Menu Item Link inside the entity template. By default, Menu Item Link is rendered in the menu-level.html.twig template. By default, this variable is set to FALSE, and we can use `hook_preprocess_menu()` to change it.

Known issues and workarounds

  1. If the menu does not have at least one field, the view modes field is not available on the Menu Item edit form. You can add an extra field and hide it on the manage form display.

  2. It does not support MenuLinkDefault entities since it has a different entity type.

Conclusion

With Menu Item Extras, we get fieldable Drupal Menus and a lot of extra features, which are helpful in building complex menus. We hope, in future, that Drupal core will support fields by default, and our module will just provide awesome extra features for Menu Items.

If you are looking to develop your Drupal-based website, feel free to contact our experts.

0 Comments
I consent Lemberg Solution Ltd collecting and using provided personal information as set out in the Privacy Policy.

Lemberg is a technology consulting, software & hardware engineering company.

Startups and established businesses rely on our industry expertise to build new products and deliver digital transformation.

Join our Newsletter?