Frage

So, I am doing a check when a user inputs an email to see if the email exists or not.

 $('form.recover-form#check-form').on('submit', function(e){

    var form    = $(this),
        input   = $('.check-recover-email'),
        span    = $('.recover-error'),
        email   = input.val();
    span.text('');
    e.preventDefault();
    $.ajax({
        url: 'ajax/check-email',
        async: 'false',
        cache: 'false',
        type: 'POST',
        data: {email: email},
        success: function(response) {
            if ( response == 'no' ) {
                span.text('email does not exist');
            } else if ( response == 'ok' ) {
                form.submit();
            }
        }
    });
});

The php code

if ( Input::isPost('email') )  {

    $email = Input::post('email');

    $check = $dbh->prepare(" SELECT * FROM users WHERE email = :email ");
    $check->execute(array( 'email' => $email ));

    echo ( $check->rowCount() == 1 ) ? 'ok' : 'no' ;

}

This way as soon as I submit the form it submits and the e.PreventDefault() inside the AJAX call is not working. If I put e.PreventDefault() before the AJAX call however, the form does not submit and the error appears if the email does not exists ( this is what I want to achieve ).

I can't understand where the problem is, hope you can help.

Thank you.

EIDT: This is the updated code

War es hilfreich?

Lösung

The problem is that you don't call preventDefault during the handling of the event. Instead, during the handling of the event, you start an ajax call (which is asynchronous), and then let the event continue. The ajax call completes later, which is too late to prevent the event's default — it's already happened.

Move the e.preventDefault() directly into the event handler, outside the ajax success handler.

$('.recover-form').on('submit', function(e){
    var form    = $(this),
        input   = $('.check-recover-email'),
        span    = $('.recover-error'),
        email   = input.val();
    span.text('');
    e.preventDefault(); // <=================== Here
    $.ajax({
        url: 'ajax/check-email',
        async: 'false',
        cache: 'false',
        type: 'POST',
        data: form.serialize(),
        success: function(response){
            if ( response == 0 ) {
                // ============================ Not here, this would be too late
                span.text('email does not exist');
            }
        }
    });
});

In a comment, you've said:

Yes, it works for the validation, but I want to submit the form if ajax returns a positive response. I only do a check with AJAX, if it fails stop the submit, if it succeed continue the submit.

You can't hold up the original form submission waiting for the result of an asynchronous ajax call. What you do instead is cancel the original form submission, do the ajax, and then if the result is okay, re-submit the form using the submit method on the raw DOM form element. That method doesn't re-trigger submit event handlers.

Example: Live copy

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<meta charset=utf-8 />
<title>Delaying form submit during ajax</title>
</head>
<body>
  <form action="http://www.google.com/search" method="GET">
    <input type="text" name="q" value="kittens">
    <input type="submit" value="Submit">
  </form>
  <script>
    (function() {
      $("form").submit(function(e) {
        var rawFormElement = this; // Remember the DOM element for the form

        // Stop form submission
        display("Got form submit event, simulating ajax");
        e.preventDefault();

        // Simulate ajax check of data
        setTimeout(function() {
          // (This is the 'success' callback for the ajax)
          display("Ajax call complete, pretending result is good and submitting");

          // All okay, go ahead and submit the form
          rawFormElement.submit(); // Doesn't trigger 'submit' handler
        }, 1500);
      });

      function display(msg) {
        $("<p>").html(String(msg)).appendTo(document.body);
      }
    })();
  </script>
</body>
</html>

Andere Tipps

You can't prevent the default action from a success handler of ajax request because of the asynchronous nature of it.

Instead by default prevent the form submission, then in the success handler if it is valid then call the submit again.

$('.recover-form').on('submit', function (e) {
    var form = $(this),
        input = $('.check-recover-email'),
        span = $('.recover-error'),
        email = input.val();
    span.text('');
    //prevent the submit
    e.preventDefault();
    $.ajax({
        url: 'ajax/check-email',
        async: 'false',
        cache: 'false',
        type: 'POST',
        data: form.serialize(),
        success: function (response) {
            if (response == 0) {
                span.text('email does not exist');
            } else {
                //submit if valie
                form[0].submit()
            }
        }
    });
});

First, you're options are incorrect. cache and async require boolean values, not strings.

async: false,
cache: false,

Secondly, instead of submitting the form after the ajax request you're instead triggering the event. Try this instead.

form.get(0).submit();

It returns the form node rather than a jquery object, allowing you to submit it directly rather than triggering an event (otherwise you would have an infinite loop.)

You don't really need async: false or cache: false in this case.

You need to do the following:

$('.recover-form').on('submit', function(e){

    e.preventDefault();

    var form    = $(this),
        input   = $('.check-recover-email'),
        span    = $('.recover-error'),
        email   = input.val();
    span.text('');
    $.ajax({
        url: 'ajax/check-email',
        async: 'false',
        cache: 'false',
        type: 'POST',
        data: form.serialize(),
        success: function(response){
            if ( response == 0 ) {
                span.text('email does not exist');
            }
        }
    });
});

Notice how I've moved the e.preventDefault() to the beginning. This is because you were calling it when the ajax request responds which might happen 100s of milliseconds or even seconds after the form has been submitted

This happens because success function passed for jQuery.ajax() is executed assyncly, then it will be executed after event handler function is finish.

You should put the e.preventDefault() out of ajax function. and everything will work.

Better you can try something like this ,

<form name="myForm" onsubmit="return submitObj.validateAndSubmit();"> <!-- your form -->

<!-- your AJAX -->

var submitObj = {
  validateAndSubmit : function()
  {
    var form    = $('.recover-form'),
        input   = $('.check-recover-email'),
        span    = $('.recover-error'),
        email   = input.val();
    span.text('');
    $.ajax({
        url: 'ajax/check-email',
        async: 'false',
        cache: 'false',
        type: 'POST',
        data: form.serialize(),
        success: function(response){
            if ( response == 0 ) {
               return false;
            }
            else{
                return true;
            }
        }
    });     

  }

};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top