You can access single value field in node template easily:

{{ content.field_test }}
or
{{ node.field_test.value }}

But iteration over multiple value fields is not pretty:

{% for key, item in content.field_tags if key|first != '#' %}
  <div class="item-{{ key + 1 }}">{{ item }}</div>
{% endfor %}

You can, of course, use a field template, but sometimes it doesn't make sense to have a ton of field template when you can simply have one node template.

Example:

I need to add "," between a field's values (a multiple value entity references field rendered in label). So I have a field template with:

{% for item in items %}
  {{ item.content }}{% if not loop.last %},{% endif %}
{% endfor %}

And in my node template I have:

{% if content.field_facilities is not empty %}
   <p>{{ content.field_facilities }}</p>
{% endif %}

But I would prefer to have a similar code directly in my node template like:

{% if content.field_facilities is not empty %}
   <p>
     {# This do not works! #}
     {% for item in content.field_facilities %}
       {{ item.content }}{% if not loop.last %},{% endif %}
     {% endfor %}
   </p>
{% endif %}

What would be the best way to solve that?

See also:

Comments

gagarine created an issue. See original summary.

gagarine’s picture

Issue summary: View changes
gagarine’s picture

Issue summary: View changes
gagarine’s picture

Issue summary: View changes
gagarine’s picture

The problem is mainly with entity reference.

One solution would be to create a twig filter passing the value to Element::children

That will then be somethings like

{% for item in content.field_tags|children %}
  <p>{{ item }}</p>
{% endfor %}

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mezitlab’s picture

Regarding Gagarin's answer, here is the code of the Twig filter that I simply put in a custom module.

mymodule/mymodule.services.yml

services:
  mymodule.twig_extension:
    arguments: ['@renderer']
    class: Drupal\mymodule\TwigExtension\Children
    tags:
      - { name: twig.extension }

mymodule/src/TwigExtension/Children.php

namespace Drupal\mymodule\TwigExtension;


class Children extends \Twig_Extension
{

  /**
   * Generates a list of all Twig filters that this extension defines.
   */
  public function getFilters()
  {
    return [
      new \Twig_SimpleFilter('children', array($this, 'children')),
    ];
  }


  /**
   * Gets a unique identifier for this Twig extension.
   */
  public function getName()
  {
    return 'mymodule.twig_extension';
  }


  /**
   * Get the children of a field (FieldItemList)
   */
  public static function Children($variable)
  {
    if (!empty($variable['#items'])
      && $variable['#items']->count() > 0
    ) {
      return $variable['#items']->getIterator();
    }

    return null;
  }

}

in the Twig template (it will result a plain-text output):

  {% for item in content.field_tags|children %}
    {{ item.get('value').getValue() }}
  {% endfor %}