function WidgetBase::formMultipleElements

Same name in other branches
  1. 8.9.x core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::formMultipleElements()
  2. 10 core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::formMultipleElements()
  3. 11.x core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::formMultipleElements()

Special handling to create form elements for multiple values.

Handles generic features for multiple fields:

  • number of widgets
  • AHAH-'add more' button
  • table display and drag-n-drop value reordering
1 call to WidgetBase::formMultipleElements()
WidgetBase::form in core/lib/Drupal/Core/Field/WidgetBase.php
Creates a form element for a field.
1 method overrides WidgetBase::formMultipleElements()
FileWidget::formMultipleElements in core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
Overrides \Drupal\Core\Field\WidgetBase::formMultipleElements().

File

core/lib/Drupal/Core/Field/WidgetBase.php, line 173

Class

WidgetBase
Base class for 'Field widget' plugin implementations.

Namespace

Drupal\Core\Field

Code

protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
    $field_name = $this->fieldDefinition
        ->getName();
    $cardinality = $this->fieldDefinition
        ->getFieldStorageDefinition()
        ->getCardinality();
    $parents = $form['#parents'];
    // Determine the number of widgets to display.
    switch ($cardinality) {
        case FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED:
            $field_state = static::getWidgetState($parents, $field_name, $form_state);
            $max = $field_state['items_count'];
            $is_multiple = TRUE;
            break;
        default:
            $max = $cardinality - 1;
            $is_multiple = $cardinality > 1;
            break;
    }
    $title = $this->fieldDefinition
        ->getLabel();
    $description = $this->getFilteredDescription();
    $elements = [];
    for ($delta = 0; $delta <= $max; $delta++) {
        // Add a new empty item if it doesn't exist yet at this delta.
        if (!isset($items[$delta])) {
            $items->appendItem();
        }
        // For multiple fields, title and description are handled by the wrapping
        // table.
        if ($is_multiple) {
            $element = [
                '#title' => $this->t('@title (value @number)', [
                    '@title' => $title,
                    '@number' => $delta + 1,
                ]),
                '#title_display' => 'invisible',
                '#description' => '',
            ];
        }
        else {
            $element = [
                '#title' => $title,
                '#title_display' => 'before',
                '#description' => $description,
            ];
        }
        $element = $this->formSingleElement($items, $delta, $element, $form, $form_state);
        if ($element) {
            // Input field for the delta (drag-n-drop reordering).
            if ($is_multiple) {
                // We name the element '_weight' to avoid clashing with elements
                // defined by widget.
                $element['_weight'] = [
                    '#type' => 'weight',
                    '#title' => $this->t('Weight for row @number', [
                        '@number' => $delta + 1,
                    ]),
                    '#title_display' => 'invisible',
                    // Note: this 'delta' is the FAPI #type 'weight' element's property.
'#delta' => $max,
                    '#default_value' => $items[$delta]->_weight ?: $delta,
                    '#weight' => 100,
                ];
            }
            $elements[$delta] = $element;
        }
    }
    if ($elements) {
        $elements += [
            '#theme' => 'field_multiple_value_form',
            '#field_name' => $field_name,
            '#cardinality' => $cardinality,
            '#cardinality_multiple' => $this->fieldDefinition
                ->getFieldStorageDefinition()
                ->isMultiple(),
            '#required' => $this->fieldDefinition
                ->isRequired(),
            '#title' => $title,
            '#description' => $description,
            '#max_delta' => $max,
        ];
        // Add 'add more' button, if not working with a programmed form.
        if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && !$form_state->isProgrammed()) {
            $id_prefix = implode('-', array_merge($parents, [
                $field_name,
            ]));
            $wrapper_id = Html::getUniqueId($id_prefix . '-add-more-wrapper');
            $elements['#prefix'] = '<div id="' . $wrapper_id . '">';
            $elements['#suffix'] = '</div>';
            $elements['add_more'] = [
                '#type' => 'submit',
                '#name' => strtr($id_prefix, '-', '_') . '_add_more',
                '#value' => t('Add another item'),
                '#attributes' => [
                    'class' => [
                        'field-add-more-submit',
                    ],
                ],
                '#limit_validation_errors' => [
                    array_merge($parents, [
                        $field_name,
                    ]),
                ],
                '#submit' => [
                    [
                        static::class,
                        'addMoreSubmit',
                    ],
                ],
                '#ajax' => [
                    'callback' => [
                        static::class,
                        'addMoreAjax',
                    ],
                    'wrapper' => $wrapper_id,
                    'effect' => 'fade',
                ],
            ];
        }
    }
    return $elements;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.