阻止表单提交 Bootstrap 5

Prevent Form Submission Bootstrap 5

我需要回答我在下面的 js 中做错了什么。我有一个 bs5 表单,如果字段留空或无效,提交不会被阻止。当字段无效但仍允许提交时,html/css 验证工作正常。

我不精通写作 javascript(如您所知),非常感谢您的帮助!

(function () {
    "use strict";

    // Fetch all the forms we want to apply custom Bootstrap validation styles to
    let forms = document.querySelectorAll(".needs-validation");

    // Loop over them and prevent submission
    Array.from(forms).forEach(function (form) {
            form.addEventListener("submit", function (event) {
                 if (!form.checkValidity()) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                        form.classList.add("was-validated");
                    }, false
            );
    });

    forms.forEach( function(e) {
    e.addEventListener('submit', function(event) {
      event.preventDefault();

      let thisForm = this;

      let action = thisForm.getAttribute('action');
      let recaptcha = thisForm.getAttribute('data-recaptcha-site-key');

      if( ! action ) {
        displayError(thisForm, 'The form action property is not set!')
        return;
      }
      thisForm.querySelector('.loading').classList.add('d-block');
      thisForm.querySelector('.error-message').classList.remove('d-block');
      thisForm.querySelector('.sent-message').classList.remove('d-block');

      let formData = new FormData( thisForm );

      if ( recaptcha ) {
        if(typeof grecaptcha !== "undefined" ) {
          grecaptcha.ready(function() {
            try {
              grecaptcha.execute(recaptcha, {action: 'php_email_form_submit'})
              .then(token => {
                formData.set('recaptcha-response', token);
                php_email_form_submit(thisForm, action, formData);
              })
            } catch(error) {
              displayError(thisForm, error)
            }
          });
        } else {
          displayError(thisForm, 'The reCaptcha javascript API url is not loaded!')
        }
      } else {
        php_email_form_submit(thisForm, action, formData);
      }
    });
  });

  function php_email_form_submit(thisForm, action, formData) {
    fetch(action, {
      method: 'POST',
      body: formData,
      headers: {'X-Requested-With': 'XMLHttpRequest'}
    })
    .then(response => {
      if( response.ok ) {
        return response.json()
      } else {
        throw new Error(`${response.status} ${response.statusText} ${response.url}`);
      }
    })
    .then(data => {
      thisForm.querySelector('.loading').classList.remove('d-block');
      if (data.type === 'success') {
        thisForm.querySelector('.sent-message').classList.add('d-block');
        thisForm.reset();
      } else {
        throw new Error(data ? data : 'Form submission failed and no error message returned from: ' + action);
      }
    })
    .catch((error) => {
      displayError(thisForm, error);
    });
  }

  function displayError(thisForm, error) {
    thisForm.querySelector('.loading').classList.remove('d-block');
    thisForm.querySelector('.error-message').innerHTML = error;
    thisForm.querySelector('.error-message').classList.add('d-block');
  }

})();

为了使第一个声明中的 event.stopPropagation() 命令生效,您必须将 true 而不是 false 传递给 [=15] 的 useCapture 参数=]函数。

否则两者将同时触发并且 none 将优先于另一个,并且 stopPropagation 将实现的唯一行为是停止从 submit 事件,这对您要实现的目标没有帮助。

编辑:正如评论中所述,另一种解决方案是让代码的验证和执行都在同一个侦听器下进行。

// code before ...
forms.forEach(function(e) {
    e.addEventListener('submit', function(event) {
        event.preventDefault();
        
        if (!e.checkValidity()) {
            e.removeClass("was-validated");
            return; // interrupts the code to happen due to being invalid
        }
        
        e.addClass("was-validated");
        //...rest of the code
    })
});
// code after ...

相关说明:为了在浏览器 Firefox

中实现相同的行为,可能需要 event.stopImmediatePropagation()