9

When using HTML form validation, having an invalid input value in a form will halt submission of that form. How can I detect that the user attempted a failed form submission? The form's onsubmit handler does not fire when submission is halted by validation failure.

I'm currently listening for keypress and click events on the submit button to detect submit attempts. Is there a better way of detecting a failed form submission?

TylerH
  • 20,799
  • 66
  • 75
  • 101
wheresrhys
  • 22,558
  • 19
  • 94
  • 162
  • 1
    Like onsubmit, and then just return false if there's an invalid entry? – oooyaya Jun 25 '13 at 15:09
  • Do you have any browser constraints? IE10 is good with HTML5 validation but the older versions are a little lacking. – Mike Robinson Jun 25 '13 at 15:12
  • like oninvalid ? O.o ? – Avner Solomon Jun 25 '13 at 15:22
  • @AvnerSolomon Yes, I think `oninvalid` is pretty close to what the OP is looking for. It seems that `oninvalid` only applies to inputs, rather than the form itself, though. Certainly you could put an `oninvalid` handler on every input -- that seems like a valid (although somewhat brittle) solution. – apsillers Jun 25 '13 at 15:32
  • @apsillers ... it doesn't work like that even id you do it via javascript. The validity property/object is defined only per input. All you can do is have a function launched onclick when the submit button is pressed and check each element. – Avner Solomon Jun 25 '13 at 15:47
  • @AvnerSolomon "`The validity property... is defined only per input.`" I completely agree, as I said above ("*...oninvalid only applies to inputs, rather than the form*"). I meant that you could use a handler function as the `oninvalid` listener on *every* validated input of the form. Thus, if there are any invalid fields, the handler will be called at least once. This is obviously brittle and suboptimal (as I said above), since you must remember to add the handler to each input. It *might* be possible to use event delegation to catch all `invalid` events that fire from inputs inside of a form. – apsillers Jun 25 '13 at 15:57
  • @apsillers your idea is good , but should be done via a javascript like this I think : http://jsfiddle.net/m2FDv/ – Avner Solomon Jun 25 '13 at 16:08
  • not sure if this is what OP is looking for – Avner Solomon Jun 25 '13 at 16:11
  • The problem with checking individual inputs is those events sometimes fire even when the form is not being submitted - they are not a good indicator for attempted form submission. @AvnerSolomon - something like an `oninvalid` event on the form is exactly what's needed (or, even better, perhaps an `onsubmitattempt`). Maybe it'll creep into the html spec at some point. It seems like a clumsy omission for there not to be an event fired at this crucial point in a HTML5 form's flow – wheresrhys Jun 25 '13 at 16:19
  • @wheresrhys ... check my jsfiddle. It's not oninvalid. It checks the validity when you submit – Avner Solomon Jun 25 '13 at 16:23
  • @Avner_Solomon I think what your `test` function does is replicate what `form.checkValidity` already does natively – wheresrhys Jun 26 '13 at 11:52
  • Can you clarify an objective metric you are seeking when you say "better"? – TylerH Aug 27 '19 at 21:19

3 Answers3

3

A simple way to get around this is to add an event listener to each input in the form to see when it has been prevented from submitting. The 'invalid' event should do everything you need.

Example

Array.prototype.slice.call(document.querySelectorAll("[required]")).forEach(function(input){
                input.addEventListener('invalid',function(e){
                    //Your input is invalid!    
                })
            });

More info here http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/

stwilz
  • 2,226
  • 2
  • 21
  • 24
3

I suggest you to use noValidate property. You can turn off default validation, and run it manually within onsubmit method

var form = document.getElementById("myForm");
form.noValidate = true; // turn off default validation

form.onsubmit = function(e) {
  e.preventDefault(); // preventing default behaviour
  this.reportValidity(); // run native validation manually

  // runs default behaviour (submitting) in case of validation success
  if (this.checkValidity()) return form.submit();

  alert('invalid'); // your code goes here
}

you can check it here: https://jsfiddle.net/titulus_desiderio/Laon29f3/

Titulus
  • 51
  • 2
2

Building on @Titulus' code above, here's how I would do it in jQuery; you can adapt this to native events if need be.

$('form-selector').on('submit', function(event) {
  // Don't do anything if constraint validation isn't supported by the browser.
  if (
    !('checkValidity' in this) ||
    // In the unlikely case this is a property but not actually a function.
    // Hypothetically, a botched polyfill could do this; it pays to be careful
    // and build resilient code.
    typeof this.checkValidity !== 'function'
  ) {
    return;
  }

  if (this.checkValidity() === true) {
    // Valid values code.
  } else {
    // Invalid values code.

    // Leave this until the last possible moment in the handler in case there's
    // an error in any of the handler code to reduce the chances of a broken
    // form where the submit does nothing. If an exception is thrown before
    // this, the browser shouldn't get this far, (hopefully) allowing the basic
    // form to still work.
    event.preventDefault();
  }
});

// Tell the browser to not validate automatically, as that would prevent submit
// from being triggered. We prevent the submission above if form doesn't pass
// validation. This is here in case there's an error in the preceding code, so
// this (hopefully) doesn't get applied in that case and browser validation
// takes place as a fallback.
this.noValidate = true;