5

I am new to Drupal and I love it very much. I am learning it on my own but I am stuck on a problem right now.

I created a custom block that display a title and a list of links. So the only fields in that blocks are of type links. It's a block for my footer region. So when the user clicks, it opens a new website in a new tab.

I want to alter the html output just for this block type, so I took out this theme suggestion: field--block-content--field-links--footer-links.html.twig

My problem is how to add a class to every <a>tag?

I tried using the module 'link class'. It works buggy. It only reads the classes that already exists in the css prior to installing the module. It doesn't read new classes created after installing the module. I tried different things, cleared the cache many times but weird. There has to be a better way to add the classes without a module.

Could anyone help me and show me the best way to add a class to my <a> tags?

Thank you :)

Here's the default template for

{% if label_hidden %}
  {% if multiple %}
    <div{{ attributes }}>
      {% for item in items %}
        <div{{ item.attributes }}>{{ item.content }}</div>
      {% endfor %}
    </div>
  {% else %}
    {% for item in items %}
     {{ item.content }}   -------------> add class here
    {% endfor %}
  {% endif %}
{% else %}
  <div{{ attributes }}>
    <div{{ title_attributes }}>{{ label }}</div>
    {% if multiple %}
      <div>
    {% endif %}
    {% for item in items %}
      <div{{ item.attributes }}>{{ item.content }}</div>
    {% endfor %}
    {% if multiple %}
      </div>
    {% endif %}
  </div>
{% endif %}
allan00958
  • 163
  • 2
  • 3
  • 13

5 Answers5

7

Replace {{ item.content }} with hardcoded link:

<a href="{{ item.content['#url']|render }}" {% if item.content['#options']['external'] %} target="_blank" {% endif %} class="some class here">{{ item.content['#title'] }}</a>

Or if you want you can merge the class options:

{{ item.content|merge({'#options': {'attributes': {'class': ['some', 'class', 'here']}}}) }}
bdrupal
  • 71
  • 1
  • 4
  • 1
    How to prevent that the content|merge affects existing attributes? In my case it deleted the title attribute. Also the anchor part was removed removed from the URL – ñull Apr 26 '19 at 14:14
5

For those who prefer to construct html render elements using php. A quite typical link :

  $elements[$delta] = [
    '#type'      => 'link',
    '#title'     => $value,
    '#url'       => Url::fromUri('mailto:' . $value),
    '#attributes' => [
      'class' => ['myClass']
    ]
  ];
Paul Leclerc
  • 1,117
  • 1
  • 14
  • 18
1

It depends on how you build that custom block. But like you said it's a bit overkill to create a new template just to add some classes.

So here are some good answers on how to create links in general and also how to add attributes like classes to them: https://drupal.stackexchange.com/questions/144992/how-do-i-create-a-link

There are slightly different answers for different situations, so look for yourself what fits your case best.

Community
  • 1
  • 1
Frank Drebin
  • 1,063
  • 6
  • 11
1

Instead of using the merge filter in the twig template that removes other attributes you can use hook_preprocess_HOOK() to add a class to the attribute class array in your-theme.theme file.

    function theme_preprocess_links__language_block(&$variables) {
    
      foreach ($variables['links'] as $i => $link) {
        $variables['links'][$i]['link']['#options']['attributes']['class'][] = 'new-class';
      }
    }
delmarr
  • 41
  • 2
0

I, too, have trouble extending the Links in Drupal 8. Menu links, comment form links, really anytime Drupal wants to render the system link values.

My attempts are usually in the pattern: 1. Try to add the class in the view when using fields, with twig override.

  1. If that's not possible, check for a theme hook, add the class via attributes. (The Chrome Drupal Template Helper extension helps.) I was able to add a class to the parent UL, but not the A's.

  2. Check for keys in the twig template and render using {{ var.name[#url] }} explicitly . (Bootstrap Drupal theme does this in their menu.html.twig!) Example:

     a href="{{ item.url }}" class="dropdown-toggle" data-target="#" data-toggle="dropdown">{{ item.title }} 
  3. If these 3 attempts fail... I add the attributes via Javascript.

    jQuery('.comment-forbidden').parent().addClass('list-unstyled');

I attempted to add classes to the node Links (login or register to post comments) in node.html.twig and was prompted with an error:

$variables['content']['links']['#attributes']['class'][] = 'list-unstyled';

When a #lazy_builder callback is specified, no properties can exist; all properties must be generated by the #lazy_builder callback. You specified the following properties: #attributes. in Drupal\Core\Render\Renderer->doRender()

stacey.mosier
  • 393
  • 2
  • 8