Score:0

Render two taxonomy fields in one alphabetical list

jp flag

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!

Score:0
jp flag

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 }}.

cn flag
`$a['#taxonomy_term']->name->getValue()[0]['value']` can be shortened to `$a['#taxonomy_term']->label()`
jp flag
@Clive thank you, I thought there must be a short cut!!
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.