function WidgetBase::formMultipleElements

Same name in other branches
  1. 9 core/lib/Drupal/Core/Field/WidgetBase.php \Drupal\Core\Field\WidgetBase::formMultipleElements()
  2. 8.9.x 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 169

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();
    $is_multiple = $this->fieldDefinition
        ->getFieldStorageDefinition()
        ->isMultiple();
    $is_unlimited_not_programmed = FALSE;
    $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_unlimited_not_programmed = !$form_state->isProgrammed();
            break;
        default:
            $max = $cardinality - 1;
            break;
    }
    $title = $this->fieldDefinition
        ->getLabel();
    $description = $this->getFilteredDescription();
    $id_prefix = implode('-', array_merge($parents, [
        $field_name,
    ]));
    $wrapper_id = Html::getUniqueId($id_prefix . '-add-more-wrapper');
    $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,
                ];
                // Add 'remove' button, if not working with a programmed form.
                if ($is_unlimited_not_programmed) {
                    $remove_button = [
                        '#delta' => $delta,
                        '#name' => str_replace('-', '_', $id_prefix) . "_{$delta}_remove_button",
                        '#type' => 'submit',
                        '#value' => $this->t('Remove'),
                        '#validate' => [],
                        '#submit' => [
                            [
                                static::class,
                                'deleteSubmit',
                            ],
                        ],
                        '#limit_validation_errors' => [],
                        '#ajax' => [
                            'callback' => [
                                static::class,
                                'deleteAjax',
                            ],
                            'wrapper' => $wrapper_id,
                            'effect' => 'fade',
                        ],
                    ];
                    $element['_actions'] = [
                        'delete' => $remove_button,
                        '#weight' => 101,
                    ];
                }
            }
            $elements[$delta] = $element;
        }
    }
    if ($elements) {
        $elements += [
            '#theme' => 'field_multiple_value_form',
            '#field_name' => $field_name,
            '#cardinality' => $cardinality,
            '#cardinality_multiple' => $is_multiple,
            '#required' => $this->fieldDefinition
                ->isRequired(),
            '#title' => $title,
            '#description' => $description,
            '#max_delta' => $max,
        ];
        // Add 'add more' button, if not working with a programmed form.
        if ($is_unlimited_not_programmed) {
            $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' => [],
                '#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.