8 – Adding attributes to a link to an uploaded file

I have been asked to add target=”_blank” to the links that are produced when a user uploads a file on a Drupal 8 site.

The field type is “File”. Multiple uploads are allowed.

Twig debug shows me that the field is being produced by the core template “file-link.html.twig”. The entire uncommented contents of that template are:

<span{{ attributes }}>{{ link }}</span>
{% if file_size %}
  {# @todo remove class before Drupal 9.0.0 #}
  <span class="file-size">({{ file_size }})</span>
{% endif %}

I brought that template into my custom theme and tried to add the attribute to the link. I thought I’d be editing the {{ link }} part of the template, changing it to attach attributes. I did variations of this:

{{ link(item.title, item.url, attributes.setAttribute(‘target’,’_blank’)) }}

Every syntax I tried produced a fatal PHP error. Thinking I was doing the attribute syntax wrong, I tested by simply trying to add a single class.

{{ link(item.title, item.url, { 'class': ('bananas') }) }}

That was still a white screen of death, so I guess I can’t use that syntax on the {{ link }} field in my file-link template.

I’ve been googling my eyeballs out of my head. I found this cool idea:

{% for item in items %}
  {{ item.content|merge({'#attributes': {'class': ('button', 'button--arrow', 'button--centered')}}) }}
{% endfor %}

so I adapted it for my field.html.twig template like so, changing this part:

{% for item in items %}
    <div{{ item.attributes }}>{{ item.content }}</div>
{% endfor %}

to this:

{% for item in items %}
      <div{{ item.attributes }}>{{ item.content|merge({'#attributes': {'target': ('_blank')}}) }}</div>
{% endfor %}

And while at least the page loaded and didn’t have a fatal error, the target attribute did not appear on the link.

Does anyone have any advice for me getting an attribute onto a file upload link? Almost everything I’ve found has to do with the link field, not the file upload field. Thanks for your time.