0

I have two term reference fields: colours and tags.

I have a poppy, it has tags: pretty and colours: red, green.

I want html like:

This flower is: green, pretty, red

i.e.

  • I want to take the terms from two fields and merge them into one collection.

I tried in Twig:

I started in twig. I could combine the terms but I couldn't sort them.

{% set alltags = content.field_tags['items']|merge(content.field_colours['items']|keys|map(i => content.field_colours[i])) %} 
{{ alltags }}

I tried in pre process

I then moved to PHP in a mytheme_preprocess_node() function. I thought I could sneak a few of the colours terms in under the tags field... It seemed to add them to the object OK, but none of the colour ones were output.

/** @var Drupal\Core\Field\EntityReferenceFieldItemList */
$coloursTags = $variables['content']['field_colours']['#items'] ?? NULL;
if ($coloursTags && $coloursTags->count()) {
  $tags = $variables['content']['field_tags']['#items'];
  foreach ($coloursTags as $item) {
    /** @var Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $item */
    $tags->appendItem($item->getValue());
  }
}

I have since found a couple of ways that work, which I'll post in an answer so as to attract better answers than mine!

1 Answer 1

0

I found a couple of ways to achieve it, posting here, but I'm open to better/cleaner ways. I'm especially unhappy in my answers with the way to access the tag name - seems so overly complicated trying to get the raw name?!

Both code blocks live in a mytheme_preprocess_node():

Answer 1: create a new variable with all the tags in it:

<?php

  $allTags = [];
  $addTags = function($fieldName) use (&$allTags, $variables) {
    if (isset($variables['content'][$fieldName])) {
      foreach (\Drupal\Core\Render\Element::children($variables['content'][$fieldName]) as $i) {
        $allTags[]= $variables['content'][$fieldName][$i];
      }
    }
  };
  $addTags('field_colours');
  $addTags('field_tags');
  usort($allTags, function ($a, $b) {
    $tagA = $a['#taxonomy_term']->name->getValue()[0]['value'];
    $tagB = $b['#taxonomy_term']->name->getValue()[0]['value'];
    return strcasecmp($tagA, $tagB);
  });
  $variables['content']['allTags'] = $allTags;

Then in Twig for the node template: {{ allTags }}.

Answer 2: mix the tags from the colour field into the tags field in the render array

<?php

  $allTagsTemp = [];
  foreach (\Drupal\Core\Render\Element::children($variables['content']['field_tags']) as $i) {
    $tag = $variables['content']['field_tags'][$i];
    unset($tag['#weight']);
    unset($variables['content']['field_tags'][$i]);
    $allTagsTemp[] = $tag;
  }
  foreach (\Drupal\Core\Render\Element::children($variables['content']['field_colours']) as $i) {
    $tag = $variables['content']['field_colours'][$i];
    unset($tag['#weight']);
    unset($variables['content']['field_colours'][$i]);
    $allTagsTemp[] = $tag;
  }
  usort($allTagsTemp, function ($a, $b) {
    $tagA = $a['#taxonomy_term']->name->getValue()[0]['value'];
    $tagB = $b['#taxonomy_term']->name->getValue()[0]['value'];
    return strcasecmp($tagA, $tagB);
  });
  $variables['content']['field_tags'] += $allTagsTemp;

Then in Twig {{ field_tags }}.

2
  • $a['#taxonomy_term']->name->getValue()[0]['value'] can be shortened to $a['#taxonomy_term']->label()
    – Clive
    Jan 20, 2022 at 19:45
  • @Clive thank you, I thought there must be a short cut!! Jan 20, 2022 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.