Skip to main content

Drupal 8: add custom field to menu and template

Updated by Tim Rabbetts on
programmer, programming, code

Had need to add custom image field to menu items.  First thing is to attach the field using this code in custom module.

function iop_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'menu_link_content') {
    $fields['menu_link_image'] = BaseFieldDefinition::create('image')
      ->setLabel(t('Menu link image'))
      ->setDescription(t('Upload the image related to this menu item'))
      ->setDisplayOptions('form', array('type' => 'string', 'weight' => 0));
    return $fields;
  }
}

This will add the field, but we need to update the db now or when you save menu item it will complain about missing columns.

drush updatedb --entity-updates

Not the new field will show and save.  But when you create a template for the menu, you will notice that this data isnt available, so you need to preprocess menu and add it.

function MYMODULE_theme_preprocess_menu(&$variables, $hook) {

  // Add the custom image field so can theme in template.
  if ($variables['theme_hook_original'] == 'menu__microsites_menu') {
    foreach ($variables['items'] as $key => &$item) {
      $entity = \Drupal::entityTypeManager()->getStorage('menu_link_content')->loadByProperties(array('uuid' => $item['original_link']->getDerivativeId()));
      if (!empty($entity)) {
        $entity = array_shift($entity);
        $image = $entity->get('menu_link_image')->entity;
        if (!empty($image)) {
          $item['image'] = $image->getFileUri();
        }
      }
    }
  }

}

Then in the menu template, e.g menu--my-menu.html.twig put this:

{% import _self as menus %}
{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
<ul{{ attributes.addClass('menu') }}>
  {% else %}
  <ul class="menu">
    {% endif %}
    {% for item in items %}
      {%
        set classes = [
        'menu-item',
        item.is_expanded ? 'menu-item--expanded',
        item.is_collapsed ? 'menu-item--collapsed',
        item.in_active_trail ? 'menu-item--active-trail',
      ]
      %}
      <li{{ item.attributes.addClass(classes) }}>
          {% if item.image is empty %}
            {{ link(item.title, item.url) }}
          {% else %}
            <a href="{{ item.url }}">
              <img src="{{ item.image | image_style('microsites_logo') }}"/>
            </a>
          {% endif %}

          {% if item.below %}
            {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
          {% endif %}
      </li>
    {% endfor %}
  </ul>
  {% endif %}
  {% endmacro %}

All done should now theme image in menu.

Comments

dark web websites <a href="https://mydarknetmarketlinks.com/ ">black internet </a> darknet markets 2024
Sat, 02/11/2024

Add new comment