🇮🇱Israel Eyal Shalev
Same as #74. I didn't patch against 8.1.x
🇮🇱Israel Eyal Shalev
- Fixed the cause of the test fail.
- Only add the remove button when the field cardinality is unlimited and it is not programmed.
🇮🇱Israel Eyal Shalev
I've found some bugs with the first patch.
The changes are:
- The ajax callback no longer return an empty element but the whole container.
- The id_prefix and wrapper_id variables are moved up in the formMultipleElements method.
- The submit method will now affect both the form_state values and the form_state user_input.
- The submit method will now only unset the choosen item but move all the items after it one delta lower.
🇮🇱Israel Eyal Shalev
I tried to replace all the [] arrays to array(). This was done manually so it could fail.
🇮🇱Israel Eyal Shalev
🇮🇱Israel Eyal Shalev
I created a working remove item button in a custom field widget using the following code:
/**
* {@inheritdoc}
*/
protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
$elements = parent::formMultipleElements($items,$form,$form_state);
$field_name = $this->fieldDefinition->getName();
$parents = $form['#parents'];
foreach (Element::children($elements) as $element_key) {
if (is_int($element_key)) {
$delta = $element_key;
$wrapper_array = array_merge($parents, [
$field_name,
$delta,
'remove',
'item'
]);
$wrapper_id = Html::getUniqueId(implode('-', $wrapper_array));
$elements[$delta]['#prefix'] = "<div id={$wrapper_id}>";
$elements[$delta]['#suffix'] = '</div>';
$elements[$delta]['remove_item'] = [
'#type' => 'submit',
'#value' => $this->t('Remove item'),
'#submit' => [[$this, 'removeItemSubmit']],
'#ajax' => [
'callback' => [$this, 'removeItemAjax'],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
'#name' => implode('_', $wrapper_array),
'#attributes' => ['class' => ['field-remove-item-submit']],
'#limit_validation_errors' => [array_merge($parents, [$field_name])],
];
}
}
return $elements;
}
public function removeItemSubmit(array $form, FormStateInterface $form_state) {
$button = $form_state->getTriggeringElement();
// Go one level up in the form, to the widgets container.
$element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
$container_element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));
$field_name = $this->fieldDefinition->getName();
$field_parents = $element['#field_parents'];
$delta = $element['#delta'];
$field_values = &$form_state->getValue($container_element['#parents']);
unset($field_values[$delta]);
// Increment the items count.
$field_state = static::getWidgetState($field_parents, $field_name, $form_state);
$field_state['items_count']--;
static::setWidgetState($field_parents, $field_name, $form_state, $field_state);
$form_state->setRebuild();
}
public function removeItemAjax(array $form, FormStateInterface $form_state) {
return [
'#type' => 'hidden',
'#attributes' => [
'data-description' => 'It is a requirement to return something to make an ajax call hide the entire element.'
]
];
}