Loading src/Element/WebformMultiple.php +31 −14 Changes for src/Element/WebformMultiple.php: 31 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -94,9 +94,14 @@ class WebformMultiple extends FormElement { $element['#min_items'] = (empty($element['#required'])) ? 0 : 1; } // Disable operation when #cardinality is set. if (!empty($element['#cardinality'])) { $element['#operations'] = FALSE; // Make sure min items does not exceed cardinality. if (!empty($element['#cardinality']) && $element['#min_items'] > $element['#cardinality']) { $element['#min_items'] = $element['#cardinality']; } // Make sure empty items does not exceed cardinality. if (!empty($element['#cardinality']) && $element['#empty_items'] > $element['#cardinality']) { $element['#empty_items'] = $element['#cardinality']; } // Add validate callback that extracts the array of items. Loading @@ -106,11 +111,6 @@ class WebformMultiple extends FormElement { // Wrap this $element in a <div> that handle #states. WebformElementHelper::fixStatesWrapper($element); if ($element['#cardinality']) { // If the cardinality is set limit number of items to this value. $number_of_items = $element['#cardinality']; } else { // Get unique key used to store the current number of items. $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items'); Loading @@ -126,17 +126,33 @@ class WebformMultiple extends FormElement { $number_of_empty_items = (int) $element['#empty_items']; $number_of_items = $number_of_default_values + $number_of_empty_items; // Make sure number of items is greated than min items. $min_items = (int) $element['#min_items']; $number_of_items = ($number_of_items < $min_items) ? $min_items : $number_of_items; // Make sure number of (default) items does not exceed cardinality. if (!empty($element['#cardinality']) && $number_of_items > $element['#cardinality']) { $number_of_items = $element['#cardinality']; } $form_state->set($number_of_items_storage_key, $number_of_items); } $number_of_items = $form_state->get($number_of_items_storage_key); } $table_id = implode('_', $element['#parents']) . '_table'; // Disable add operation when #cardinality is met. if (!empty($element['#cardinality']) && $number_of_items >= $element['#cardinality']) { $element['#add'] = FALSE; } // Add wrapper to the element $element += [ '#prefix' => '<div id="' . $table_id .'">', '#suffix' => '</div>', ]; // DEBUG: // Disable Ajax callback by commenting out the below callback and wrapper. $ajax_settings = [ Loading Loading @@ -188,7 +204,7 @@ class WebformMultiple extends FormElement { } // Build table. $attributes = ['id' => $table_id, 'class' => ['webform-multiple-table']]; $attributes = ['class' => ['webform-multiple-table']]; if (count($element['#element']) > 1) { $attributes['class'][] = 'webform-multiple-table-responsive'; } Loading Loading @@ -225,7 +241,7 @@ class WebformMultiple extends FormElement { } // Build add items actions. if (empty($element['#cardinality'])) { if (empty($element['#cardinality']) || ($number_of_items < $element['#cardinality'])) { $element['add'] = [ '#prefix' => '<div class="webform-multiple-add js-webform-multiple-add container-inline">', '#suffix' => '</div>', Loading @@ -238,12 +254,13 @@ class WebformMultiple extends FormElement { '#ajax' => $ajax_settings, '#name' => $table_id . '_add', ]; $max = ($element['#cardinality']) ? $element['#cardinality'] - $number_of_items : 100; $element['add']['more_items'] = [ '#type' => 'number', '#title' => $element['#add_more_button_label'] . ' ' . $element['#add_more_input_label'], '#title_display' => 'invisible', '#min' => 1, '#max' => 100, '#max' => $max, '#default_value' => $element['#add_more'], '#field_suffix' => $element['#add_more_input_label'], '#error_no_message' => TRUE, Loading Loading @@ -837,7 +854,7 @@ class WebformMultiple extends FormElement { $button = $form_state->getTriggeringElement(); $parent_length = (isset($button['#row_index'])) ? -4 : -2; $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, $parent_length)); return $element['items']; return $element; } /** Loading @@ -852,7 +869,7 @@ class WebformMultiple extends FormElement { $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items'); $number_of_items = $form_state->get($number_of_items_storage_key); if ($number_of_items || $element['#cardinality']) { if (!empty($values['items']) && ($number_of_items || $element['#cardinality'])) { $items = $values['items']; // Validate unique keys. Loading src/Tests/Composite/WebformCompositeCustomTest.php +2 −1 Changes for src/Tests/Composite/WebformCompositeCustomTest.php: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -29,7 +29,8 @@ class WebformCompositeCustomTest extends WebformTestBase { // Check basic custom composite. $this->assertRaw('<label for="edit-webform-custom-composite-basic">webform_custom_composite_basic</label>'); $this->assertRaw('<div id="webform_custom_composite_basic_table" class="webform-multiple-table webform-multiple-table-responsive">'); $this->assertRaw('<div id="webform_custom_composite_basic_table">'); $this->assertRaw('<div class="webform-multiple-table webform-multiple-table-responsive">'); $this->assertRaw('<th class="webform_custom_composite_basic-table--handle webform-multiple-table--handle"><span class="visually-hidden">Re-order</span></th>'); $this->assertRaw('<th class="webform_custom_composite_basic-table--first_name webform-multiple-table--first_name">First name</th>'); $this->assertRaw('<th class="webform_custom_composite_basic-table--last_name webform-multiple-table--last_name">Last name</th>'); Loading src/Tests/Element/WebformElementValidateMultipleTest.php +11 −0 Changes for src/Tests/Element/WebformElementValidateMultipleTest.php: 11 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -24,6 +24,17 @@ class WebformElementValidateMultipleTest extends WebformElementTestBase { // Check that only three textfields are displayed. $this->assertFieldByName('webform_element_multiple_textfield_three[items][0][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][1][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][2][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][3][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three_table_add'); // Add 2 more items. $edit = [ 'webform_element_multiple_textfield_three[add][more_items]' => 2 ]; $this->drupalPostAjaxForm(NULL, $edit, 'webform_element_multiple_textfield_three_table_add'); $this->assertFieldByName('webform_element_multiple_textfield_three[items][0][_item_]'); $this->assertFieldByName('webform_element_multiple_textfield_three[items][1][_item_]'); $this->assertFieldByName('webform_element_multiple_textfield_three[items][2][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][3][_item_]'); Loading src/Tests/Element/WebformElementValidateUniqueTest.php +8 −1 Changes for src/Tests/Element/WebformElementValidateUniqueTest.php: 8 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -62,13 +62,20 @@ class WebformElementValidateUniqueTest extends WebformElementTestBase { $this->assertNoRaw('unique_error error message.'); $this->assertNoRaw('unique_ignored error message.'); // Check #unique multiple validation within the same element. // @see \Drupal\webform\Plugin\WebformElementBase::validateUniqueMultiple // Add 2 more items. $edit = [ 'unique_textfield_multiple[add][more_items]' => 2 ]; $this->drupalPostAjaxForm('webform/test_element_validate_unique', $edit, 'unique_textfield_multiple_table_add'); $edit = [ 'unique_textfield_multiple[items][0][_item_]' => '{same}', 'unique_textfield_multiple[items][2][_item_]' => '{same}', ]; $this->postSubmission($webform, $edit); $this->drupalPostForm(NULL, $edit, t('Submit')); $this->assertRaw('unique_textfield_multiple error message.');; // Purge existing submissions. Loading Loading
src/Element/WebformMultiple.php +31 −14 Changes for src/Element/WebformMultiple.php: 31 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -94,9 +94,14 @@ class WebformMultiple extends FormElement { $element['#min_items'] = (empty($element['#required'])) ? 0 : 1; } // Disable operation when #cardinality is set. if (!empty($element['#cardinality'])) { $element['#operations'] = FALSE; // Make sure min items does not exceed cardinality. if (!empty($element['#cardinality']) && $element['#min_items'] > $element['#cardinality']) { $element['#min_items'] = $element['#cardinality']; } // Make sure empty items does not exceed cardinality. if (!empty($element['#cardinality']) && $element['#empty_items'] > $element['#cardinality']) { $element['#empty_items'] = $element['#cardinality']; } // Add validate callback that extracts the array of items. Loading @@ -106,11 +111,6 @@ class WebformMultiple extends FormElement { // Wrap this $element in a <div> that handle #states. WebformElementHelper::fixStatesWrapper($element); if ($element['#cardinality']) { // If the cardinality is set limit number of items to this value. $number_of_items = $element['#cardinality']; } else { // Get unique key used to store the current number of items. $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items'); Loading @@ -126,17 +126,33 @@ class WebformMultiple extends FormElement { $number_of_empty_items = (int) $element['#empty_items']; $number_of_items = $number_of_default_values + $number_of_empty_items; // Make sure number of items is greated than min items. $min_items = (int) $element['#min_items']; $number_of_items = ($number_of_items < $min_items) ? $min_items : $number_of_items; // Make sure number of (default) items does not exceed cardinality. if (!empty($element['#cardinality']) && $number_of_items > $element['#cardinality']) { $number_of_items = $element['#cardinality']; } $form_state->set($number_of_items_storage_key, $number_of_items); } $number_of_items = $form_state->get($number_of_items_storage_key); } $table_id = implode('_', $element['#parents']) . '_table'; // Disable add operation when #cardinality is met. if (!empty($element['#cardinality']) && $number_of_items >= $element['#cardinality']) { $element['#add'] = FALSE; } // Add wrapper to the element $element += [ '#prefix' => '<div id="' . $table_id .'">', '#suffix' => '</div>', ]; // DEBUG: // Disable Ajax callback by commenting out the below callback and wrapper. $ajax_settings = [ Loading Loading @@ -188,7 +204,7 @@ class WebformMultiple extends FormElement { } // Build table. $attributes = ['id' => $table_id, 'class' => ['webform-multiple-table']]; $attributes = ['class' => ['webform-multiple-table']]; if (count($element['#element']) > 1) { $attributes['class'][] = 'webform-multiple-table-responsive'; } Loading Loading @@ -225,7 +241,7 @@ class WebformMultiple extends FormElement { } // Build add items actions. if (empty($element['#cardinality'])) { if (empty($element['#cardinality']) || ($number_of_items < $element['#cardinality'])) { $element['add'] = [ '#prefix' => '<div class="webform-multiple-add js-webform-multiple-add container-inline">', '#suffix' => '</div>', Loading @@ -238,12 +254,13 @@ class WebformMultiple extends FormElement { '#ajax' => $ajax_settings, '#name' => $table_id . '_add', ]; $max = ($element['#cardinality']) ? $element['#cardinality'] - $number_of_items : 100; $element['add']['more_items'] = [ '#type' => 'number', '#title' => $element['#add_more_button_label'] . ' ' . $element['#add_more_input_label'], '#title_display' => 'invisible', '#min' => 1, '#max' => 100, '#max' => $max, '#default_value' => $element['#add_more'], '#field_suffix' => $element['#add_more_input_label'], '#error_no_message' => TRUE, Loading Loading @@ -837,7 +854,7 @@ class WebformMultiple extends FormElement { $button = $form_state->getTriggeringElement(); $parent_length = (isset($button['#row_index'])) ? -4 : -2; $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, $parent_length)); return $element['items']; return $element; } /** Loading @@ -852,7 +869,7 @@ class WebformMultiple extends FormElement { $number_of_items_storage_key = static::getStorageKey($element, 'number_of_items'); $number_of_items = $form_state->get($number_of_items_storage_key); if ($number_of_items || $element['#cardinality']) { if (!empty($values['items']) && ($number_of_items || $element['#cardinality'])) { $items = $values['items']; // Validate unique keys. Loading
src/Tests/Composite/WebformCompositeCustomTest.php +2 −1 Changes for src/Tests/Composite/WebformCompositeCustomTest.php: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -29,7 +29,8 @@ class WebformCompositeCustomTest extends WebformTestBase { // Check basic custom composite. $this->assertRaw('<label for="edit-webform-custom-composite-basic">webform_custom_composite_basic</label>'); $this->assertRaw('<div id="webform_custom_composite_basic_table" class="webform-multiple-table webform-multiple-table-responsive">'); $this->assertRaw('<div id="webform_custom_composite_basic_table">'); $this->assertRaw('<div class="webform-multiple-table webform-multiple-table-responsive">'); $this->assertRaw('<th class="webform_custom_composite_basic-table--handle webform-multiple-table--handle"><span class="visually-hidden">Re-order</span></th>'); $this->assertRaw('<th class="webform_custom_composite_basic-table--first_name webform-multiple-table--first_name">First name</th>'); $this->assertRaw('<th class="webform_custom_composite_basic-table--last_name webform-multiple-table--last_name">Last name</th>'); Loading
src/Tests/Element/WebformElementValidateMultipleTest.php +11 −0 Changes for src/Tests/Element/WebformElementValidateMultipleTest.php: 11 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -24,6 +24,17 @@ class WebformElementValidateMultipleTest extends WebformElementTestBase { // Check that only three textfields are displayed. $this->assertFieldByName('webform_element_multiple_textfield_three[items][0][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][1][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][2][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][3][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three_table_add'); // Add 2 more items. $edit = [ 'webform_element_multiple_textfield_three[add][more_items]' => 2 ]; $this->drupalPostAjaxForm(NULL, $edit, 'webform_element_multiple_textfield_three_table_add'); $this->assertFieldByName('webform_element_multiple_textfield_three[items][0][_item_]'); $this->assertFieldByName('webform_element_multiple_textfield_three[items][1][_item_]'); $this->assertFieldByName('webform_element_multiple_textfield_three[items][2][_item_]'); $this->assertNoFieldByName('webform_element_multiple_textfield_three[items][3][_item_]'); Loading
src/Tests/Element/WebformElementValidateUniqueTest.php +8 −1 Changes for src/Tests/Element/WebformElementValidateUniqueTest.php: 8 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -62,13 +62,20 @@ class WebformElementValidateUniqueTest extends WebformElementTestBase { $this->assertNoRaw('unique_error error message.'); $this->assertNoRaw('unique_ignored error message.'); // Check #unique multiple validation within the same element. // @see \Drupal\webform\Plugin\WebformElementBase::validateUniqueMultiple // Add 2 more items. $edit = [ 'unique_textfield_multiple[add][more_items]' => 2 ]; $this->drupalPostAjaxForm('webform/test_element_validate_unique', $edit, 'unique_textfield_multiple_table_add'); $edit = [ 'unique_textfield_multiple[items][0][_item_]' => '{same}', 'unique_textfield_multiple[items][2][_item_]' => '{same}', ]; $this->postSubmission($webform, $edit); $this->drupalPostForm(NULL, $edit, t('Submit')); $this->assertRaw('unique_textfield_multiple error message.');; // Purge existing submissions. Loading