137

I have a form that, when submitted, I need to do some additional processing before it should submit the form. I can prevent default form submission behavior, then do my additional processing (it's basically calling Google Maps API and adding a few hidden fields to the form) -- and then I need the form to submit.

Is there a way to "prevent default", then some point later "continue default?"

StackOverflowNewbie
  • 39,403
  • 111
  • 277
  • 441
  • @FelixKling Did you mean http://stackoverflow.com/questions/7610871/how-to-trigger-an-event-after-using-event-preventdefault? – M. Mimpen Feb 11 '15 at 11:56

10 Answers10

85

Use jQuery.one()

Attach a handler to an event for the elements. The handler is executed at most once per element per event type

$('form').one('submit', function(e) {
    e.preventDefault();
    // do your things ...

    // and when you done:
    $(this).submit();
});

The use of one prevent also infinite loop because this custom submit event is detatched after the first submit.

Aurel
  • 3,682
  • 1
  • 19
  • 22
57

When you bind the .submit() event to the form, and you do the things you want to do before returning (true), these things happen prior to the actual submission.

For example:

$('form').submit(function(){
    alert('I do something before the actual submission');
    return true;
});

Simple example

Another example on jquery.com: http://api.jquery.com/submit/#entry-examples

Ron van der Heijden
  • 14,803
  • 7
  • 58
  • 82
  • 2
    are you saying that the form will not submit until all code before the "return true;" statement is executed? – developarvin Jan 17 '13 at 09:01
  • 2
    Yes that is exactly what the [submit()](http://api.jquery.com/submit/#entry-examples) function does. – Ron van der Heijden Jan 17 '13 at 09:02
  • 14
    It's not a good example becayse it's synchronyous. What if the stuff I need to do is async call? So the case is "click submit -> do async stuff and dont' submit the form -> in async callback fill some fields in the form -> submit the form from the callback" – The Godfather Oct 11 '16 at 14:49
  • 1
    What about run some async jQuery code?! Will work too? – candlejack Dec 25 '16 at 23:42
  • this works great for me. I use it to control things before submitting and if things are not right I use "return false". I have looked for this solution for a day. thanks alot. – livefreeor Oct 11 '17 at 20:12
  • in my case I use parsley and my own validation so with form submit button click event can't handle to submit the form after validation is valid, but your code works perfect. VERY THANKS. – Ozal Zarbaliyev Jan 04 '19 at 07:59
32

I would just do:

 $('#submiteButtonID').click(function(e){
     e.preventDefault();
     //do your stuff.
     $('#formId').submit();
 });

Call preventDefault at first and use submit() function later, if you just need to submit the form

halfer
  • 19,824
  • 17
  • 99
  • 186
bipen
  • 36,319
  • 9
  • 49
  • 62
  • don't involve logic inside your click event handler. delegate it to others responsibility. – Royi Namir Jan 17 '13 at 08:55
  • 37
    This assumes the sure will click a button. What if the user just hits the "enter" button from within the form? That will also submit the form. So, it's probably not a good idea to rely on the submit button getting clicked. – StackOverflowNewbie Jan 17 '13 at 09:08
  • i was just giving an example of a click... since there was no related codes mentioned on the question.... – bipen Jan 17 '13 at 09:38
  • 2
    In any case, the snippet you gave will only work should the user click a button. That's not how forms work. Any other suggestions? – StackOverflowNewbie Jan 17 '13 at 10:49
  • bind the click, prevent its default and trigger the submit button click – candlejack Dec 25 '16 at 23:43
  • In this case the `e.preventDefault()` is not needed because you're only preventing the execution of other handlers on the button, not the form. – gyo Jan 24 '19 at 17:22
22
      $('#myform').on('submit',function(event){
        // block form submit event
        event.preventDefault();

        // Do some stuff here
        ...

        // Continue the form submit
        event.currentTarget.submit();
  });
Udy Warnasuriya
  • 959
  • 2
  • 12
  • 23
20

Using this way You will do a endless Loop on Your JS. to do a better way you can use the following

var on_submit_function = function(evt){
    evt.preventDefault(); //The form wouln't be submitted Yet.
    (...yourcode...)

    $(this).off('submit', on_submit_function); //It will remove this handle and will submit the form again if it's all ok.
    $(this).submit();
}

$('form').on('submit', on_submit_function); //Registering on submit.

I hope it helps! Thanks!

Joepreludian
  • 980
  • 9
  • 11
  • the best way actually, variation with async function - https://gist.github.com/BjornMelgaard/8ba0ee9d07c20dd8c8b3550c9df3e9ef – srghma Jan 18 '18 at 11:22
  • @bjornmelgaard I have to remember that the async is [non standard](https://developer.mozilla.org/en-US/docs/Web/API/Document/async). – Valerio Bozz Feb 12 '18 at 09:52
11

This is, IMHO, the most generic and robust solution (if your actions are user-triggered, eg 'user clicks on a button'):

  • the first time a handler is called check WHO triggered it:
    • if a user tiggered it - do your stuff, and then trigger it again (if you want) - programmatically
    • otherwise - do nothing (= "continue default")

As an example, note this elegant solution to adding "Are you sure?" popup to any button just by decorating a button with an attribute. We will conditionally continue default behavior if the user doesn't opt out.

1. Let's add to every button that we want an "are you sure" popup a warning text:

<button class="btn btn-success-outline float-right" type="submit"  ays_text="You will lose any unsaved changes... Do you want to continue?"                >Do something dangerous</button>

2. Attach handlers to ALL such buttons:

$('button[ays_text]').click(function (e, from) {
    if (from == null) {  // user clicked it!
        var btn = $(this);
        e.preventDefault();
        if (confirm() == true) {
            btn.trigger('click', ['your-app-name-here-or-anything-that-is-not-null']);
        }
    }
    // otherwise - do nothing, ie continue default
});

That's it.

igorludi
  • 1,519
  • 2
  • 18
  • 31
5

With jQuery and a small variation of @Joepreludian's answer above:

Important points to keep in mind:

  • .one(...) instead on .on(...) or .submit(...)
  • named function instead of anonymous function since we will be referring it within the callback.

$('form#my-form').one('submit', function myFormSubmitCallback(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var $this = $(this);
    if (allIsWell) {
        $this.submit(); // submit the form and it will not re-enter the callback because we have worked with .one(...)
    } else {
        $this.one('submit', myFormSubmitCallback); // lets get into the callback 'one' more time...
    }
});

You can change the value of allIsWell variable in the below snippet to true or false to test the functionality:

$('form#my-form').one('submit', function myFormSubmitCallback(evt){
  evt.stopPropagation();
  evt.preventDefault();
  var $this = $(this);
  var allIsWell = $('#allIsWell').get(0).checked;
  if(allIsWell) {
    $this.submit();
  } else {
    $this.one('submit', myFormSubmitCallback);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/" id="my-form">
  <input name="./fname" value="John" />
  <input name="./lname" value="Smith" />
  <input type="submit" value="Lets Do This!" />
  <br>
  <label>
    <input type="checkbox" value="true" id="allIsWell" />
    All Is Well
  </label>
</form>

Good Luck...

Aakash
  • 21,375
  • 7
  • 100
  • 81
  • Are you sure `stopPropagation` is needed here? Also you can create a name less function (remove `myFormSubmitCallback`) – Melroy van den Berg Apr 21 '22 at 22:20
  • 1
    @MelroyvandenBerg, `stopPropagation` is not needd but we did that to avoid the event from propagating to other elements. You can remove it if you want the event to propagate - the core functionality of this solution will not be affected. And the reason we have used a `named` function is so that we can refer it within the function recursively. – Aakash Apr 22 '22 at 14:08
3

"Validation injection without submit looping":

I just want to check reCaptcha and some other stuff before HTML5 validation, so I did something like that (the validation function returns true or false):

$(document).ready(function(){
   var application_form = $('form#application-form');

   application_form.on('submit',function(e){

        if(application_form_extra_validation()===true){
           return true;
        }

        e.preventDefault();

   });
});
Dennis Heiden
  • 757
  • 8
  • 16
3

In a pure Javascript way, you can submit the form after preventing default.

This is because HTMLFormElement.submit() never calls the onSubmit(). So we're relying on that specification oddity to submit the form as if it doesn't have a custom onsubmit handler here.

var submitHandler = (event) => {
  event.preventDefault()
  console.log('You should only see this once')
  document.getElementById('formId').submit()
}

See this fiddle for a synchronous request.


Waiting for an async request to finish up is just as easy:

var submitHandler = (event) => {
  event.preventDefault()
  console.log('before')
  setTimeout(function() {
    console.log('done')
    document.getElementById('formId').submit()
  }, 1400);
  console.log('after')
}

You can check out my fiddle for an example of an asynchronous request.


And if you are down with promises:

var submitHandler = (event) => {
  event.preventDefault()
  console.log('Before')
    new Promise((res, rej) => {
      setTimeout(function() {
        console.log('done')
        res()
      }, 1400);
    }).then(() => {
      document.getElementById('bob').submit()
    })
  console.log('After')
}

And here's that request.

alairock
  • 1,826
  • 1
  • 21
  • 28
  • Is there a generic way in just plain javascript, not jquery or any libraries, modules, etc, to execute the "default action" of the specific triggered event after preventing default and executing your code? uh, delayDefault? – jdmayfield Nov 06 '21 at 06:55
  • @jdmayfield Perhaps just put the default action code into a function. Then you can use it as both the default action and a delayed action after preventing the default. – alairock Jan 12 '22 at 04:56
1

You can use e.preventDefault() which will stop the current operation.

than you can do$("#form").submit();

 $('#form').submit(function (e)
{
    return !!e.submit;
});
if(blabla...)
{...
}
else
{
    $('#form').submit(
    {
        submit: true
    });
}
Royi Namir
  • 144,742
  • 138
  • 468
  • 792