2

I have a Drupal content type that uses multiple referenced entities of the same type (say, "related products")

I want to give the title field of every related product a unique ID. It can be the product name, an iterator, the ID of the product's node, whichever is easiest.

I created a twig template that overrides the title of said node in said content type: field--node--title--my-content-type.html.twig but I have no idea where to go from here.

I can add a custom id with

{% set attributes = attributes.setAttribute('id', 'customID') %}

but that's static, and would not be unique when the field is called multiple times.

{% set node = element['#object'] %} and {{ item.content['#node'].field_name.value }} as recommended here don't work for me.

If possible, I want to solve it twig-only, without any additional php code.

any pointers or suggestions are much appreciated

Zsolt Balla
  • 533
  • 2
  • 7
  • 16

3 Answers3

1

You can modify the code that loops through the items array.

For example, I added an iteration index:

field--node--title--my-content-type.html.twig

{# Here I coppied template from web/core/modules/system/templates/field.html.twig and modified it #}
{%
  set title_classes = [
  label_display == 'visually_hidden' ? 'visually-hidden',
]
%}

{% if label_hidden %}
  {% if multiple %}
    <div{{ attributes }}>
      {% for item in items %}
        <div{{ item.attributes }}>{{ item.content }}</div>
      {% endfor %}
    </div>
  {% else %}
    {% for item in items %}
      <div{{ attributes }}>{{ item.content }}</div>
    {% endfor %}
  {% endif %}
{% else %}
  <div{{ attributes }}>
    <div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
    {% if multiple %}
    <div>
      {% endif %}
      {% for index, item in items %}                                     {# use index #}
        <span>{{ index }}</span>                                         {# and print it #}
        <div{{ item.attributes }}>{{ item.content }}</div>
      {% endfor %}
      {% if multiple %}
    </div>
    {% endif %}
  </div>
{% endif %}

Result:

enter image description here

Kien Nguyen
  • 2,616
  • 2
  • 7
  • 24
  • 1
    Thanks, you're a hero. While your solution didn't work for me out of the box, it did put me in the right direction and helped develop the solution that does exactly what I was after (see my answer for details). So I will mark your answer as accepted, as my solution builds on your logic. thanks again – Zsolt Balla Jan 20 '21 at 06:48
  • @ZsoltBalla Because you wrote "it can be an iterator", so maybe I misunderstood what you wanted. But anyway, I'm glad I helped you somewhat. – Kien Nguyen Jan 20 '21 at 07:58
0

The answer by Kien Nguyen did not exactly work for me as is, since while there were multiple referenced entities, but each of those had only one title, so the index always ended up being '0', which wasn't exactly a value I could use as a unique ID.

But building on his logic, It was now easy to arrive to a solution:

Instead of using the index as index, I used it as a key to access the value in item.content. (Since I was about to use item.content as the unique ID I had to get rid of the spaces, but in order to do that, I had to directly access the value in the item.content array.

In my scenario the item is a title for a 'related product' type of node, so it's

  • short enough to be used as a HTML id
  • unique (ie. there are no two different products with the same name)

so the

{% for index, item in items %}                                     {# use index #}
        <span>{{ index }}</span>                                         {# and print it #}
        <div{{ item.attributes }}>{{ item.content }}</div>

part in Kien's code became

{% for key, item in items %}
      <span id="{{element['#items'][key].value|replace({' ':''}) }}"></span>
      <div{{ item.attributes }}>{{ item.content }}</div>
    

in my implementation, which then provides me with a unique ID for every referenced node, as originally intended.

Thanks for your help, Kien!

Zsolt Balla
  • 533
  • 2
  • 7
  • 16
0

You can use twig random() for this and even set delimiters on the value, for example random(1, 50)

Source

Shawn W
  • 566
  • 4
  • 13