Commit 1153746d authored by jrockowitz's avatar jrockowitz Committed by jrockowitz

Issue #2984983 by jrockowitz: Required fields inside a composite are validated...

Issue #2984983 by jrockowitz: Required fields inside a composite are validated for empty rows when "Allowed number of values" is limited to a specific number
parent 3af61a05
......@@ -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.
......@@ -106,37 +111,48 @@ 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');
// Store the number of items which is the number of
// #default_values + number of empty_items.
if ($form_state->get($number_of_items_storage_key) === NULL) {
if (empty($element['#default_value']) || !is_array($element['#default_value'])) {
$number_of_default_values = 0;
}
else {
$number_of_default_values = count($element['#default_value']);
}
$number_of_empty_items = (int) $element['#empty_items'];
$number_of_items = $number_of_default_values + $number_of_empty_items;
// Get unique key used to store the current number of items.
$number_of_items_storage_key = static::getStorageKey($element, 'number_of_items');
// Store the number of items which is the number of
// #default_values + number of empty_items.
if ($form_state->get($number_of_items_storage_key) === NULL) {
if (empty($element['#default_value']) || !is_array($element['#default_value'])) {
$number_of_default_values = 0;
}
else {
$number_of_default_values = count($element['#default_value']);
}
$number_of_empty_items = (int) $element['#empty_items'];
$number_of_items = $number_of_default_values + $number_of_empty_items;
$min_items = (int) $element['#min_items'];
$number_of_items = ($number_of_items < $min_items) ? $min_items : $number_of_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;
$form_state->set($number_of_items_storage_key, $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'];
}
$number_of_items = $form_state->get($number_of_items_storage_key);
$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 = [
......@@ -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';
}
......@@ -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>',
......@@ -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,
......@@ -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;
}
/**
......@@ -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.
......
......@@ -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>');
......
......@@ -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_]');
......
......@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment