1

My form onSubmit is calling:

onsubmit="validate(this); return false;"

validate(); is as follows:

function validate(obj) {
    $.ajax({
        url : "ajax/validate_check.php",
        type : "POST",
        data : $("#" + obj.id).serialize(),
        success : function(data) {
            $('#' + obj.id + ' :input.form_errors').removeClass('form_errors')
            data = $.parseJSON(data);
            if(data['error_count'] >= 1) {
                $.each(data, function(i, item) {
                    $('#' + i).addClass('form_errors');
                });
            } else {
                $('#' + obj.id).submit();
            }
        }
    });
}

When I have 0 errors it's trying to submit the form but I'm getting an infinite loop. I realize it's happening because my onSubmit calls the function again. How do I actually submit the form when I'm ready?

EDIT:

I'm just looking for the best way to approach this. I want to validate onSubmit for a quick response to the user and then I want to actually submit the form that way I know where the data is going (eg register.php will register a user).

That's why I'm not doing a combined action/validate script because I wouldn't know which form I'm submitting. I probably need to rearrange the way I'm doing this.

halfer
  • 19,824
  • 17
  • 99
  • 186
SeanWM
  • 16,789
  • 7
  • 51
  • 83

6 Answers6

1

Remove onsubmit="validate(this); return false;"

And use the following function:

$('form').submit(function(e){
    e.preventDefault();
    var $form = $(this),
        $formId = $form.attr('id'),
        $formName = $form.attr('name');

    $.ajax({
        url : "ajax/validate_check.php",
        type : "POST",
        data : $("#" + $formId).serialize(),
        success : function(data) {
            $('#' + $formId + ' :input.form_errors').removeClass('form_errors')
            data = $.parseJSON(data);
            if(data['error_count'] >= 1) {
                $.each(data, function(i, item) {
                    $('#' + i).addClass('form_errors');
                });
            } else {
                document.forms[$formName].submit();
            }
        }
    });
});

Fiddle where you can test with form id or name: http://jsfiddle.net/67rvg/3/

jk.
  • 14,365
  • 4
  • 43
  • 58
  • Thanks! This is more like what I'm looking for. I'm having an issue with the submit though. I get the error `Uncaught TypeError: Property 'submit' of object # is not a function`. I tried to do `$('#' + $formId).submit()` instead but then I get an infinite loop again. Any ideas? – SeanWM Mar 26 '13 at 03:05
  • @SeanWM Could be browser issue with form submit. Give the edited answer a try. – jk. Mar 26 '13 at 03:45
  • @SeanWM Check for a `form` or `input` element with the `id` or `name` submit. That can cause your error. See http://stackoverflow.com/questions/12540953/property-submit-of-object-htmlformelement-is-not-a-function – jk. Mar 26 '13 at 03:50
  • Thanks, I'll try it when I get home. – SeanWM Mar 26 '13 at 12:19
  • 1
    I took the submit button name out because it was named `submit`. Your link helped! Thanks a lot. – SeanWM Mar 26 '13 at 21:03
0

i'd not issue another submit in your else branch, but return a true value.

in your onsubmit i'd do onsubmit="return validate(this);"

Cristian
  • 23
  • 1
  • 5
  • 1
    Returning `true` with an asynchronous `ajax` call is not going to work. `submit` should be called in the `success` function. The `onsubmit` attribute should be avoided as @moonwave99 suggests. Since we can't see if there is a submit button from the OP's question, we are left with few options for solutions. @balexandre took the best shot at it so far. – jk. Mar 24 '13 at 00:25
0

Don't submit it again using the submit call, as you say, you will be in a loop... just post everything like a submit:

change your $('#' + obj.id).submit(); line by submitForm() and add

function submitForm() {
    var form = $("#my_form"),
        url = form.attr("action"),
        dt = form.serialize();

    $.post(url, dt, function(data) {
       // your form was post'd successfully
    });
}

Now that you know how to work, why inventing the well?

Why don'y you use jQuery Validate and the remote validation to do the job for you?

balexandre
  • 73,608
  • 45
  • 233
  • 342
0

This should work: Unbind the event before re-submitting.

Instead of

function validate(obj) {
    $.ajax({
        url : "ajax/validate_check.php",
        type : "POST",
        data : $("#" + obj.id).serialize(),
        success : function(data) {
            $('#' + obj.id + ' :input.form_errors').removeClass('form_errors')
            data = $.parseJSON(data);
            if(data['error_count'] >= 1) {
                $.each(data, function(i, item) {
                    $('#' + i).addClass('form_errors');
                });
            } else {
                $('#' + obj.id).submit();
            }
        }
    });
}

Try

function validate(obj) {
    $.ajax({
        url : "ajax/validate_check.php",
        type : "POST",
        data : $("#" + obj.id).serialize(),
        success : function(data) {
            $('#' + obj.id + ' :input.form_errors').removeClass('form_errors')
            data = $.parseJSON(data);
            if(data['error_count'] >= 1) {
                $.each(data, function(i, item) {
                    $('#' + i).addClass('form_errors');
                });
            } else {
                $('#' + obj.id).unbind('submit').submit();
            }
        }
    });
}
GVdP
  • 165
  • 8
0

In your block

   } else {
        $('#' + obj.id).submit();
   }

Rather than do an actual form submission use another ajax call to send your data to your forms action endpoint:

} else {

    $.ajax({
        url : obj.action
        ,type : obj.method
        ,data : $(obj).serialize()
        ,success : function() {
            // show success message/close window/ etc
        }
        , error: function() {
            // show error saving form message
        }
    });
}

This way you'll be in a better position to capture the results if something goes wrong with the form submission.

Michael MacDonald
  • 708
  • 1
  • 6
  • 24
0
  1. Don't use the onsubmit attribute, it's mixing JavaScript into html markup, and goes against best practices.
  2. Why don't you make the validation part of the register function (server side). That way you aren't making twice as many round trips as you need. Following best practices you should be making as few http requests as possible. You can organize your php scripts into folders depending on the functionality. Much easier to tell what form is being submitted. This way it will also be much easier to create a unique validation script for each form submission. You may also be able to use the REQUEST_URI Server variable to tell which form you are submitting.

See here for instructions on accessing the REQUEST URI of the request within a php script.

If there is a common validation that you are doing for every form submitted, you can move that into a separate php file and import it into all files that will use the function. That function will then be available inside the script you imported it into.

See here for instructions on including files in php.

Then you can add custom validation to each individual script. You will more than likely need custom validation for some of your forms, someday.

  • util/validation_util.php
  • ajax/user/register.php
  • ajax/user/login.php
  • ajax/user/logout.php
  • ajax/product/search.php
  • ajax/product/detail.php
  • ajax/product/addToCart.php
  • etc...

    $('#formId').on('submit', function (event) {
    
    event.preventDefault();
    
    $.ajax({
        url : "ajax/user/register.php",
        type : "POST",
        data : $(this).serialize(),
        success : function(data) {
            $('#' + obj.id + ' :input.form_errors').removeClass('form_errors')
            data = $.parseJSON(data);
            if(data['error_count'] >= 1) {
                $.each(data, function(i, item) {
                    $('#' + i).addClass('form_errors');
                });
            }
        }
    });
    });
    
Rick Suggs
  • 1,582
  • 1
  • 15
  • 30