How do I hide an empty field if my custom field formatter removes all items? I have a custom field formatter (in Drupal 8) that displays a list of taxonomy terms on a node. Some terms are not meant to be displayed, so the field formatter removes them from the items list.

Occasionally, all items are removed -- yet the HTML elements that wrap the field are still rendered. How do I hide the field completely when all items are removed?

EDIT FOR CLARITY:

I have a field with machine name field_tags that is an entity reference to multiple taxonomy terms.

To render this field, I wrote a custom formatter as a field formatter plugin in a custom module. The code is stored in the standard location in mymodule/src/Plugin/Field/FieldFormatter/TermListFormatter.php

My class extends EntityReferenceFormatterBase.

In my class, my viewElements() method strips out some items as needed and sometimes returns an empty array if no items should be rendered.

  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];

    // Loop through each of the terms in this field.
    foreach ($this-&gt;getEntitiesToView($items, $langcode) as $delta =&gt; $entity) {
      $label = $entity-&gt;label();

      // ONLY show taxonomy terms that begin with "Test".
      if (mb_substr($label, 0, 5) === 'Test') {
        $options = [
          'query' =&gt; [
            'tags' =&gt; [$entity-&gt;id()],
          ],
        ];

        // Output terms as links to /test?tags[]={tid}
        $elements[$delta] = [
          '#type' =&gt; 'link',
          '#title' =&gt; $label,
          '#url' =&gt; Url::fromRoute('view.test.page_1'),
          '#options' =&gt; $options,
        ];

        if (!empty($items[$delta]-&gt;_attributes)) {
          $elements[$delta]['#options'] += ['attributes' =&gt; []];
          $elements[$delta]['#options']['attributes'] += $items[$delta]-&gt;_attributes;
          // Unset field item attributes since they have been included in the
          // formatter output and shouldn't be rendered in the field template.
          unset($items[$delta]-&gt;_attributes);
        }

        $elements[$delta]['#cache']['tags'] = $entity-&gt;getCacheTags();
      }
    }

    // This will be an empty array if there were no terms beginning with "Test"
    return $elements;
  }


When all the terms are stripped out, the field wrapper elements are still output as follows:

&lt;span class="views-field views-field-field-tags"&gt;
  &lt;span class="field-content"&gt;&lt;/span&gt;
&lt;/span&gt;


How do I stop these elements from appearing when there are no terms to show?
Drupal adds the field wrapper only if the result returned by viewElements() contains at least one renderable child.

FormatterBase::view():

  public function view(FieldItemListInterface $items, $langcode = NULL) {
    ...
    $elements = $this-&gt;viewElements($items, $langcode);

    // If there are actual renderable children, use #theme =&gt; field, otherwise,
    // let access cacheability metadata pass through for correct bubbling.
    if (Element::children($elements)) {
      $entity = $items-&gt;getEntity();
      $entity_type = $entity-&gt;getEntityTypeId();
      $field_name = $this-&gt;fieldDefinition-&gt;getName();
      $info = [
        '#theme' =&gt; 'field',
        '#title' =&gt; $this-&gt;fieldDefinition-&gt;getLabel(),
        '#label_display' =&gt; $this-&gt;label,
        '#view_mode' =&gt; $this-&gt;viewMode,
        '#language' =&gt; $items-&gt;getLangcode(),
        '#field_name' =&gt; $field_name,
        '#field_type' =&gt; $this-&gt;fieldDefinition-&gt;getType(),
        '#field_translatable' =&gt; $this-&gt;fieldDefinition-&gt;isTranslatable(),
        '#entity_type' =&gt; $entity_type,
        '#bundle' =&gt; $entity-&gt;bundle(),
        '#object' =&gt; $entity,
        '#items' =&gt; $items,
        '#formatter' =&gt; $this-&gt;getPluginId(),
        '#is_multiple' =&gt; $this-&gt;fieldDefinition-&gt;getFieldStorageDefinition()-&gt;isMultiple(),
      ];

      $elements = array_merge($info, $elements);
    }

    return $elements;
  }


This means for the question if the field formatter removes all items the field is hidden.

However, field formatter and field preprocessing handle empty fields differently. If you only remove the first field item it is possible that the condition for an empty field has different results. See How to print all values of a multi-value field, except the first?