Adding custom attributes

Last updated on
23 August 2024

New Attributes

If you wish to use an attribute not listed in the existing list, add a mymodule.link_attributes.yml file to the root directory of your custom module and define new attributes e.g.

(Make sure the link_attributes module is enabled and your link field is using the "Link (with attributes)" widget on the "Manage form display" page.)

aria-role:
  title: Aria Role
lang:
  title: Language
  type: select
  empty_value: ''
  options:
    en: English
    de: German
icon:
  title: Icon
  type: select
  empty_value: ''
  options:
    facebook: Facebook
    instagram: Instagram
    twitter: Twitter
    vimeo: Vimeo
    linkedin: LinkedIn
display_text:
  title: Display text with the icon?
  type: select
  empty_value: ''
  options:
    yes: Yes
    no: No
download:
  title: 'Download filename'

Then follow the steps below to add that field to configurable or base fields.

Alter Configurable Fields

If you wish to alter a configurable field, under "Manage form display", the new attributes will appear in the field's widget settings. Alternatively, export it as a .yml file, add in the extra attributes, and re-import it.

To add a new link attribute to a base field, such as Menu Link Content's link field, you need a custom implementation of hook_entity_base_field_info_alter in a custom module/profile.

YOURMODULENAME.module should look something like this:

function YOURMODULENAME_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'menu_link_content') {
    $fields['link']->setDisplayOptions('form', [
      'type' => 'link_attributes',
      'weight' => -2,
      'settings' => [
        'enabled_attributes' => [
          'id' => FALSE,
          'name' => FALSE,
          'target' => TRUE,
          'rel' => TRUE,
          'class' => TRUE,
          'accesskey' => FALSE,
          // Add your own custom attributes as required.
          'YOURCUSTOMATTRIBUTE' => TRUE,
        ],
      ],
    ]);
  }
}

Note that you may need to add a hook_module_implements_alter to make sure your module runs after link_attributes if your module name is sorted before link_attributes. Eg, if your module is called something.module, you are fine - because something comes after link_attributes when the hooks are sorted alphabetically. But if your module is called anything.module, you will need the hook_module_implements_alter.

Accessing Your Attributes In Twig

Using the base Drupal 8 menu.html.twig file as an example. If you wanted to access a custom attributes "icon" and "display_text":

{% import _self as menus %}

{#
  We call a macro which calls itself to render the full tree.
  @see https://twig.symfony.com/doc/1.x/tags/macro.html
#}
{{ 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 }}>
    {% else %}
      <ul>
    {% endif %}
    {% for item in items %}
      {# Look for our custom attributes and do a thing. #}
      {% if item.url.options.attributes.icon is defined and
        (item.url.options.attributes.display_text is defined == false or 
         item.url.options.attributes.display_text != 'yes') %}
        {# The icon attribute exists and we do not want to show a title #}
        {% set item = item|merge({title: null}) %}
      {% endif %}
      {# @todo Do something with our icon attribute #}
      <li{{ item.attributes }}>
        {{ link(item.title, item.url) }}
        {% if item.below %}
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}

Accessing Your Attributes In PHP

/** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $item */
$item;
$attributes = $item->link->getUrlObject()->getOptions()['attributes'] ?? [];

Help improve this page

Page status: No known problems

You can: