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.
Article content
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.
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.
You can add view modes for Menus from the default page with view modes for all entity types.
Menu Item Extras provides an additional overview page with a list of all menu items and their view modes.
Since each menu item could have child items, the module provides an extra field “Children” on the manage display.
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).
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.
Now we can place our views block in the region and see what we get.
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.
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
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.
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.