11

I want to count the number of values of unlimited field in twig tempalate I tried

{{ node.field_mytext.count }} => faced with error

and in another try

{{ content.field_mytext.count }} => nothing returned

(in this method I checked my field is not in disabled field is display manager).


My question is how can I count the number of items of a field in Twig?

I hope I face with the solutions expect these solutions :D

1
  • did you try {{ content.field_mytext | length }}? Jul 21, 2016 at 11:58

5 Answers 5

17

{{ node.field_mytext.count }} => faced with error

This does not work, because the method count is not allowed in twig policies:

core/lib/Drupal/Core/Template/TwigSandboxPolicy.php

{{ content.field_mytext | length }}?

This does not work, because content is a render array with a lot of additional keys.

This works: Convert field to array and count

{{ node.field_mytext.getvalue | length }}
1
  • you could probably also do it with a foreach loop, but this is cleaner for this specific purpose.
    – No Sssweat
    Jul 21, 2016 at 13:22
10

Easiest way is to get the ['#items']|length. I do it all the time for counting items for view more instances and when loading sliders.

{{ content.field_mytext['#items']|length }}
2
  • many thanks to you! But for me it only works if there are multiple items, if its only one i get a debug backtrace ..
    – john Smith
    Mar 1, 2023 at 7:54
  • okay i figured out it was because i was using {{ kint(content.field_x['#items']|length) }} to debug which for some reason fails if output is 1
    – john Smith
    Mar 1, 2023 at 8:08
4

I've used own Twig filters to support entity fields, with this you can use fields as native arrays:

{{ content.field_mytext|length }}

or

{{ content.field_mytext|first|value }}

or

{% if content.field_mytext is empty %}

You can easily add you own Twig filters via a custom module. You can learn more here: drupal.org/docs/8/creating-custom-modules. In short you need to create a module directory, for example path/to/drupal/modules/custom/common/, put there common.info.yml with module definition and common.services.yml with definition of service (see comments in code) and put my code to /path/to/drupal/modules/custom/common/src/TwigExtension.php.

<?php
namespace Drupal\common;

use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\TypedData\ComplexDataInterface;

/**
 * A class providing Twig extensions.
 *
 * This provides a Twig extension that registers various Field-API-specific
 * extensions to Twig, overriding empty and array related filters.
 *
 * Don't forget about common.services.yml
 * services:
 *   common.twig.TwigExtension:
 *     class: Drupal\common\TwigExtension
 *     tags:
 *       - { name: twig.extension }
 *
 * Usage (in *.html.twig file):
 *   - check is field empty {% if content.field_foo is empty %}
 *   - get field first value {{ content.field_foo|first|value }}
 */
class TwigExtension extends \Twig_Extension {

  /**
   * {@inheritdoc}
   */
  public function getTests() {
    return [
      new \Twig_SimpleTest('empty', [$this, 'twigEmptyField']),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getFilters() {
    return [
      new \Twig_SimpleFilter('length', [$this, 'twigLengthFilter'], ['needs_environment' => TRUE]),
      new \Twig_SimpleFilter('slice', [$this, 'twigSlice'], ['needs_environment' => TRUE]),
      new \Twig_SimpleFilter('first', [$this, 'twigFirst'], ['needs_environment' => TRUE]),
      new \Twig_SimpleFilter('last', [$this, 'twigLast'], ['needs_environment' => TRUE]),
      new \Twig_SimpleFilter('value', [$this, 'twigFieldValue']),
    ];
  }

  /**
   * Check if value is field item object.
   *
   * @param mixed $value
   *   Mixed Twig variable.
   *
   * @return \Drupal\Core\Field\FieldItemListInterface|mixed
   *   FieldItemListInterface or same value as passed.
   */
  private function checkItems($value) {
    if (is_array($value) && !empty($value['#items']) && $value['#items'] instanceof FieldItemListInterface) {
      return $value['#items'];
    }
    return $value;
  }

  /**
   * Get field item value.
   *
   * @param object $field
   *   Field object.
   *
   * @return array|mixed
   *   List of values or value.
   */
  public function twigFieldValue($field) {
    if ($field instanceof FieldItemInterface) {
      $prop = $field->mainPropertyName();
      $value = $field->getValue();
      return $prop ? $value[$prop] : $value;
    }
    if ($field instanceof FieldItemListInterface) {
      $value = [];
      foreach ($field as $item) {
        $value[] = $this->twigFieldValue($item);
      }
      return $value;
    }
    return '';
  }

  /**
   * Checks if a variable is empty.
   *
   * @see twig_test_empty
   */
  public function twigEmptyField($value) {
    $value = $this->checkItems($value);
    if ($value instanceof ComplexDataInterface) {
      return $value->isEmpty();
    }
    // Return TRUE, because there is no data only cache and weight.
    elseif (!is_object($value) && isset($value['#cache']) && count($value) == 2) {
      return TRUE;
    }
    return twig_test_empty($value);
  }

  /**
   * Returns the length of a variable.
   *
   * @param \Twig_Environment $env
   *   Twig environment.
   * @param mixed $item
   *   A variable.
   *
   * @return mixed
   *   The first element of the item.
   *
   * @see twig_length_filter
   */
  public function twigLengthFilter(\Twig_Environment $env, $item) {
    $item = $this->checkItems($item);
    return twig_length_filter($env, $item);
  }

  /**
   * Slices a variable.
   *
   * @param \Twig_Environment $env
   *   Twig environment.
   * @param mixed $item
   *   A variable.
   * @param int $start
   *   Start of the slice.
   * @param int $length
   *   Size of the slice.
   * @param bool $preserveKeys
   *   Whether to preserve key or not (when the input is an array)
   *
   * @return mixed
   *   The first element of the item.
   *
   * @see twig_slice
   */
  public function twigSlice(\Twig_Environment $env, $item, $start, $length = NULL, $preserveKeys = FALSE) {
    $item = $this->checkItems($item);
    return twig_slice($env, $item, $start, $length, $preserveKeys);
  }

  /**
   * Returns the first element of the item.
   *
   * @param \Twig_Environment $env
   *   Twig environment.
   * @param mixed $item
   *   A variable.
   *
   * @return mixed
   *   The first element of the item.
   *
   * @see twig_first
   */
  public function twigFirst(\Twig_Environment $env, $item) {
    $item = $this->checkItems($item);
    return twig_first($env, $item);
  }

  /**
   * Returns the last element of the item.
   *
   * @param \Twig_Environment $env
   *   Twig environment.
   * @param mixed $item
   *   A variable.
   *
   * @return mixed
   *   The first element of the item.
   *
   * @see twig_last
   */
  public function twigLast(\Twig_Environment $env, $item) {
    $item = $this->checkItems($item);
    return twig_last($env, $item);
  }

}
0
1

Works together with https://www.drupal.org/project/twig_field_value.

{% if content.field_paragraphs|field_value|length > 1 %}
  {# Do something. #}
{% endif %}
-1

Use length filter

{{ content.field_mytext | length }} 
2
  • 4
    return mistake value !!!, my field is long and I have 4 item in there but return 20 !!!
    – Yuseferi
    Jul 21, 2016 at 12:04
  • 1
    this can (depending on circumstances) can return the correct values, but it is an inaccurate answer.
    – aydow
    Feb 22, 2019 at 1:03

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.