in Jquery how to run code with callback before submit
Asked Answered
S

4

5

I need to run some jquery code before submitting a form and there seem to be some issues.

Just hear me out before you rush to recommend this:

$(function() {
     $('form').submit( function() {
         /* some code */
         return true;
     });
});

I need , after pressing the "submit" button first calculate the longtitude and latitude variables of an address using google API and then submit the form. That requires listening for a response in a callback function.

The code I have so far looks like this:

  $("form input:submit").click(function(e){
      e.preventDefault();
      var address = $(this).find('.address').val();
      geocoder.geocode( { 'address': unescape(address)}, function(results, status) 
      {
          if (status == google.maps.GeocoderStatus.OK) 
          {
            $(".latSelector input:hidden").val(results[0].geometry.location.lat());
            $(".lngSelector input:hidden").val(results[0].geometry.location.lng());
            $("form").submit();
          }
       });  
  });

If I do the same using the "submit" function, the form submits before the callback function is triggered and the code behind executes with missing values.

If I use the "click" event on the button like the code above and submit manually, then the code executes correctly but the submit doesn't trigger the code behind of the form.

I think I am close to getting this to work but I can't find the magic combination that will run the code, process the callback values and then submit the form correctly, so that the code behind executes.

Stewartstewed answered 9/1, 2013 at 16:39 Comment(2)
What do you mean "the submit doesn't trigger the code behind of the form?"Unhandy
When you press submit, there's a .NET code in the background to handle the click which fires off an email. The email is never sentStewartstewed
R
12

You should use the submit event on the form, not the click event of the button. Some browsers allow the form to be submitted without using the submit button by just pressing enter when some field in the form has focus.

The preventDefault method will stop the submitting of the form, so that you can submit it later:

$("form").submit(function(e){
  e.preventDefault();
  var address = $(this).find('.address').val();
  geocoder.geocode( { 'address': unescape(address)}, function(results, status) 
  {
      if (status == google.maps.GeocoderStatus.OK) 
      {
        $(".latSelector input:hidden").val(results[0].geometry.location.lat());
        $(".lngSelector input:hidden").val(results[0].geometry.location.lng());
        $("form")[0].submit();
      }
   });  
});

Edit:

To submit the form using the button, you need to keep track of why the form is submitted:

var reason = 'user';

$("form").submit(function(e){
  if (reason == 'user') {
    e.preventDefault();
    var address = $(this).find('.address').val();
    geocoder.geocode( { 'address': unescape(address)}, function(results, status) 
    {
      if (status == google.maps.GeocoderStatus.OK) 
      {
        $(".latSelector input:hidden").val(results[0].geometry.location.lat());
        $(".lngSelector input:hidden").val(results[0].geometry.location.lng());
        reason = 'callback';
        $("form input:submit").click();
      }
    });
  }
});
Ribaldry answered 9/1, 2013 at 16:53 Comment(5)
just wondering.. will doing $("form").submit(); trigger that same event handler causing a loop?Considerable
@Guffa, I was formulating the same answer, but in testing it in jsfiddle, it seems that this becomes recursive, as the $("form").submit() calls the handler again. Am I missing something?Sunshine
@wirey: It shouldn't, as submitting the form with code doesn't trigger the submit event. However, testing this it seems that jQuery has a different opinion, and will trigger the submit event when you use the submit method. The solution is to use the native submit method instead of the jQuery submit method, which doesn't do this. I have adjusted the code above.Ribaldry
I had already tried that before writing to stackoverflow and can verify the solution didn't seem to work for me. The code run successfully but the internal "submit" failed to do anything.Stewartstewed
@Nick: I see, you are depending on a specific button submitting the form. You could use a variable to keep track of whether the form was submitted from a user click or from the callback, and then trigger the click event on the button to submit the form from the callback. I added some code above.Ribaldry
P
2

Simply:

  1. call the callback function.
  2. return false when submit is thrown by the user (i.e. don't submit).
  3. at the end of the callback, put a code that do the submit with trigger function

Fast example code:

$('elem').click(function{
  callback();
  return false;
})

and in callback() you should submit the form. This is a good practice also when you execute transitions.

EDIT TO ANSWER TO YOUR COMMENT For sake of completenes, I will provide the full example for my answer. Please, consider that my answer does not require further variables, as suggested by Guffa.

You can check it here, and here follows the code:

$('input[type="submit"]').click(function(e){
    var address = 'London, UK';
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode( { 'address': unescape(address)}, function(results, status){
      if (status == google.maps.GeocoderStatus.OK) 
      {
        $(".latSelector input:hidden").val(results[0].geometry.location.lat());
        $(".lngSelector input:hidden").val(results[0].geometry.location.lng());
        alert("DATA TAKEN BEFORE TO SUBMIT");
        $('form').submit();
      }
    });

  return false;
});

Finally, consider that the common user will do as follows:

  1. User click the submit button
  2. User suppose to see the subsequent page, while the client is waiting for the callback to be complete.
  3. So, impatient user will click again to the send button.

Hence, I also suggest to disable the submit button after that "click" event is triggered by the user.

Finally, I suggest to always use return false instead of preventDefault() in order to stop such a event propagation, read here why.

Peag answered 9/1, 2013 at 16:42 Comment(3)
this looks almost same as my solution. I've added the "return false" at the end and it's still not working. It seems to be submitting but it doesn't trigger the code behindStewartstewed
Did you triggered the submit inside the callback, just after the lat and long have been retrieved?Peag
However, now you can see my working example! It doesn't use additional variables.Peag
S
2

I've come up with a probably simpler solution to avoid Guffa's initial submission loop.

Once the callback ends, simply unbind (using unbind() or off()) submit handler and then do the submit the form. The loop is broken;)

Sam answered 5/5, 2013 at 21:20 Comment(0)
S
0

This may be against some arbitrary standard acceptable practice, but I would just prevent form submission via the enter key with something like this:

$('form').bind("keyup keypress", function(e) {
  var pressedKey = e.keyCode || e.which; 
  if (pressedKey  == 13) {               
    e.preventDefault();
    return false;
  }
});

Then I would set the actual submit button to display:none and use a element to fire the original code you had in the question using .click() as suggested by Guffa. Done deal without the extraneous User/Callback conditional logic.

$("button#Submit").click(function(){
      var address = $("form").find('.address').val();
      geocoder.geocode( { 'address': unescape(address)}, function(results, status) 
      {
          if (status == google.maps.GeocoderStatus.OK) 
          {
            $(".latSelector input:hidden").val(results[0].geometry.location.lat());
            $(".lngSelector input:hidden").val(results[0].geometry.location.lng());
            $("form input:submit").click();
          }
       });  
  });
Silverplate answered 29/4, 2014 at 20:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.