Verified Commit 4fbd912d authored by Dave Long's avatar Dave Long
Browse files

Issue #3333481 by phthlaap, galileo25, dmitry.korhov, smustgrave, mdolnik,...

Issue #3333481 by phthlaap, galileo25, dmitry.korhov, smustgrave, mdolnik, quietone, nod_, alieffring: Collapsed Details Element causes JS Error for required fields

(cherry picked from commit a31d15a8)
parent 5540b5f8
Loading
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -28,4 +28,17 @@
    'formFragmentLinkClickOrHashChange.details',
    handleFragmentLinkClickOrHashChange,
  );

  /**
   * Binds a listener to handle required fields in details elements.
   */
  window.addEventListener(
    'invalid',
    (event) => {
      if (event.target.matches('details input[required]')) {
        handleFragmentLinkClickOrHashChange(event, $(event.target));
      }
    },
    { capture: true },
  );
})(jQuery);
+9 −0
Original line number Diff line number Diff line
@@ -433,6 +433,15 @@ form_test.details_form:
  requirements:
    _access: 'TRUE'

form_test.details_contains_required_textfield:
  path: '/form_test/details-contains-required-textfield/{use_ajax}'
  defaults:
    _form: '\Drupal\form_test\Form\FormTestDetailsContainsRequiredTextfieldForm'
    _title: 'Form details contains required textfield test'
    use_ajax: FALSE
  requirements:
    _access: 'TRUE'

form_test.description_display:
  path: '/form_test/form-descriptions'
  defaults:
+64 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\form_test\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Builds a form to test a required textfield within a details element.
 *
 * @internal
 */
class FormTestDetailsContainsRequiredTextfieldForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'form_test_details_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $use_ajax = FALSE): array {

    $form['meta'] = [
      '#type' => 'details',
      '#title' => 'Details element',
      '#open' => FALSE,
    ];
    $form['meta']['required_textfield_in_details'] = [
      '#type' => 'textfield',
      '#required' => TRUE,
      '#title' => 'Required textfield',
    ];
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => 'Submit',
    ];
    if ($use_ajax) {
      $form['submitAjax'] = [
        '#type' => 'submit',
        '#value' => 'Submit Ajax',
        '#ajax' => [
          'callback' => '::submitForm',
          'event' => 'click',
          'wrapper' => 'form-test-details-form',
        ],
      ];
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    return $form;
  }

}
+49 −0
Original line number Diff line number Diff line
@@ -165,4 +165,53 @@ public function testVerticalTabValidationVisibility() {
    $this->assertNotNull($assert_session->waitForElementVisible('css', '[name="element_2"].error'));
  }

  /**
   * Tests form submit with a required field in closed details element.
   */
  public function testDetailsContainsRequiredTextfield(): void {
    $this->drupalGet('form_test/details-contains-required-textfield');
    $details = $this->assertSession()->elementExists('css', 'details[data-drupal-selector="edit-meta"]');

    // Make sure details element is not open at the beginning.
    $this->assertFalse($details->hasAttribute('open'));

    $textfield = $this->assertSession()->elementExists('css', 'input[name="required_textfield_in_details"]');

    // The text field inside the details element is not visible too.
    $this->assertFalse($textfield->isVisible(), 'Text field is not visible');

    // Submit the form with invalid data in the required fields.
    $this->assertSession()
      ->elementExists('css', 'input[data-drupal-selector="edit-submit"]')
      ->click();
    // Confirm the required field is visible.
    $this->assertTrue($textfield->isVisible(), 'Text field is visible');
  }

  /**
   * Tests required field in closed details element with ajax form.
   */
  public function testDetailsContainsRequiredTextfieldAjaxForm(): void {
    $this->drupalGet('form_test/details-contains-required-textfield/true');
    $assert_session = $this->assertSession();
    $textfield = $assert_session->elementExists('css', 'input[name="required_textfield_in_details"]');

    // Submit the ajax form to open the details element at the first time.
    $assert_session->elementExists('css', 'input[value="Submit Ajax"]')
      ->click();

    $assert_session->waitForElementVisible('css', 'input[name="required_textfield_in_details"]');

    // Close the details element.
    $assert_session->elementExists('css', 'form summary')
      ->click();

    // Submit the form with invalid data in the required fields without ajax.
    $assert_session->elementExists('css', 'input[data-drupal-selector="edit-submit"]')
      ->click();

    // Confirm the required field is visible.
    $this->assertTrue($textfield->isVisible(), 'Text field is visible');
  }

}