0

I need to validate a HTML form before executing the action attribute. But it gives me a hard time. Please see the comment in the else statement, and the comment after returning false for an explanation of this issue

$(document).ready(function(){
    $("#ajax-payment-form").submit(function() {
        var str = $(this).serialize();
        $.ajax({
            type: "POST",
            url: templateDir+"/payment_form/payment_process.php",
            data: str,
            success: function(msg) {
                // Message Sent - Show the 'Thank You' message and hide the form
                if(msg == 'OK') {
                    alert("success");
                } else {
                    event.preventDefault(); // I have tried with or without this method
                    alert("fail");
                }
            }
        });
        return false; // when return false, the action will not execute. If false is removed the action will execute, even if event.precentDefault(); is called in the else statement.**
    });                                                         
});

Thanks for your time,

Troels

thar
  • 1,094
  • 2
  • 13
  • 25
  • If you want to validate before submission, use `.preventDefault()` upon submit, and then manually submit the form using `.submit()` when validation has been performed and passed. – Terry Oct 25 '14 at 19:04
  • Can you please show an example using the code I posted? – thar Oct 25 '14 at 19:17

2 Answers2

0

Your ajax call is asynchronous. This means that this function is executed, and it doesn't wait for a response from the function before it proceeds forward. This means that return false; will always fire before the result of the ajax function returns to you. Given your current circumstances, the easiest thing to do is call this.submit() from within the success function, but always return false; under the default scenario. This will avoid recursion, and also the asynchronous call won't be problematic anymore.

$(document).ready(function(){
    $("#ajax-payment-form").submit(function() {
        var str = $(this).serialize();
        $.ajax({
            type: "POST",
            url: templateDir+"/payment_form/payment_process.php",
            data: str,
            context: this, //needed to tell the ajax function that "this" belongs to the form, not the ajax call.
            success: function(msg) {
                // Message Sent - Show the 'Thank You' message and hide the form
                if(msg == 'OK') {
                    alert("success");
                    this.submit(); //it's magic, john.
                } else {
                    //no reason to prevent the default, as the form will automatically return false anyway.
                    alert("fail");
                }
            }
        });
        return false; //just leave this right here.
    });                                                         
});
Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
  • Thanks for your reply, unfortunately this is not fixing the issue. the else statement perform well, but the if condition is not? seems like this.submit() not execution the action attribute. any idea? – thar Oct 25 '14 at 19:16
  • this.submit(); should call the underlieing DOM handler on the object, so if the `action` attribute is not correct and you need to add `templateDir` to it like you've done in the ajax call, then you'll need to modify that in the success function and then call submit. Furthermore, it may be a scoping issue. Try defining `var that = this;` after `var str = $(this).serialize();`, and then use `that.submit();` in the `if(msg == 'OK'){`. Lastly, check your web inspector (press F12) and go to the network tab. This will tell you everything about your request. – Ohgodwhy Oct 25 '14 at 19:18
  • The `this` is not referencing the right object in the `$.ajax` function. You should declare the context of the `$.ajax` call using `context: this`. See: http://stackoverflow.com/questions/6394812/this-inside-of-ajax-success-not-working – Terry Oct 25 '14 at 19:18
  • @Terry Yep! Although I didn't advise to use Context, which is likely a better solution, and instead just advised OP to create a reference. I'll update. – Ohgodwhy Oct 25 '14 at 19:20
  • Unfortunately context: this is not helping to fix the problem. It seems like the return false statement prevent this.submit(); from working? – thar Oct 25 '14 at 19:30
  • @thar then use the method I described earlier by declaring the form as `var that = this;` outside of the `$.ajax()` call – Ohgodwhy Oct 25 '14 at 20:05
0

The issue is two fold: event is not declared in your function call, and that you are not submitting the form upon the success funtion. The logic of your submit event should be as follow:

  1. Listen to submit event on the <form> element.
  2. Prevent default form actions first, using e.preventDefault()
  3. Make AJAX call. Depending on the outcome of the returned data, determine whether to proceed with submitting the form. I strongly suggest not using the deprecated jqXHR.success function, but the deferred functions jqXHR.done() or jqXHR.fail().

Also, you can always use console.log() to check your script, instead of relying on alert() which blocks downstream code execution. Here's the code:

$(function(){
    $("#ajax-payment-form input[type='submit']").click(function(e) {

        // Prevent form submission
        e.preventDefault();

        // Serialize data, make AJAX call
        var str = $(this).closest('form').serialize();
        $.ajax({
            type: "POST",
            url: templateDir+"/payment_form/payment_process.php",
            data: str,
            context: this    // So that you can use $(this) later
        }).done(function(msg) {
            // If a response is received from your server
            if(msg == 'OK') {
                 console.log('Validation passed, will submit form');
                 $(this).closest('form').submit();
            } else {
                 console.log('Validation failed, will not do anything more');
            }
        }).fail(function() {
            // Catch ajax errors here
            console.log('AJAX error');
        });
    });                                                         
});
Terry
  • 63,248
  • 15
  • 96
  • 118
  • Thanks terry. It seems like a infinity loop is being executed. In the console it says (1023)Validation passed, will submit form. the number in () is counting up FAST. – thar Oct 25 '14 at 19:36
  • @thar My bad. This is because triggering form submission results in a recursive function call (as we are listening to the form submission event, too!). I suggest listening to the click event of the submit button (be it the ` – Terry Oct 25 '14 at 19:43
  • thanks there is no loop anymore, so long so good. But now it returns Validation failed, will not do anything more theme.js?ver=4.0:77 also when the form is ok? – thar Oct 25 '14 at 19:49
  • Check your server response of the `msg`. What do you see? – Terry Oct 25 '14 at 20:15
  • there is just a "blank" message in the console and a reference to theme.js?ver=4.0:77 ? But after trying to log an string instead of msg, I can see that it is the else statement there is being executed. – thar Oct 25 '14 at 20:21
  • If `msg` returns blank, your `if` statement is not going to pass. – Terry Oct 25 '14 at 22:35
  • this var str = $(this).serialize(); is the problem, iam back to the first method var str = $("#ajax-payment-form").serialize(); The only thing not working now, is the submit() – thar Oct 25 '14 at 22:52
  • Oh, yes. Since you're not using the form, you'll have to transverse up and serialize the form itself, i.e. `$(this).closest('form').serialize()`. – Terry Oct 25 '14 at 23:17
  • Substitute the original line with the serialize method. – Terry Oct 25 '14 at 23:30
  • haven't seen that you also updated your example. Unfortunately it still not working. the submit is not executing. I can see that you are from denmark, can we talk danish about this issue some where? – thar Oct 25 '14 at 23:43
  • I think the problem is that e.preventDefault(); of the click event also prevents the submission of the form. If i try to put e.precentDefault(); in else, the submit works. But then it submits also when the else statement is being executed. – thar Oct 26 '14 at 00:05
  • But that is the main point — to avoid submititng the form by default, until you receive further information from the server, whose returned data was evaluated conditionally whether to proceed to manual submission of the form. – Terry Oct 26 '14 at 10:01