2

There was an error in my code and there was also a js file included inside my page which prevented anything from executing inside $(document).ready(function () { ...

i'm trying to sumbit this login form:

<form class="form" id="AjaxForm">
        <input type="text" name="username" placeholder="Username">
        <input type="password" name="password" placeholder="Password">
        <button type="submit" id="login-button">Login</button>
</form>

Via ajax with this code:

var request;
$("#AjaxForm").submit(function(event){

    // Abort any pending request
    if (request) {
        request.abort();
    }
    // setup some local variables
    var $form = $(this);

    // Let's select and cache all the fields
    var $inputs = $form.find("input, select, button, textarea");

    // Serialize the data in the form
    var serializedData = $form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    $inputs.prop("disabled", true);

    // Fire off the request to /form.php
    request = $.ajax({
        url: "login.php",
        type: "post",
        data: serializedData
    });

    // Callback handler that will be called on success
    request.done(function (response, textStatus, jqXHR){
        // Log a message to the console
        console.log("Hooray, it worked!");
    });

    // Callback handler that will be called on failure
    request.fail(function (jqXHR, textStatus, errorThrown){
        // Log the error to the console
        console.error(
            "The following error occurred: "+
            textStatus, errorThrown
        );
    });

    // Callback handler that will be called regardless
    // if the request failed or succeeded
    request.always(function () {
        // Reenable the inputs
        $inputs.prop("disabled", false);
    });

    // Prevent default posting of form
    event.preventDefault();
  });

Which i found here: jQuery Ajax POST example with PHP

I'm trying to post it to login.php which checks if it is a valid username and password. But when i press the Login button it just puts the username and the password in the url and does nothing. And when i add action="login.php" method="POST" It submits the form but not via ajax because when i comment the ajax code out it still submits. I'm trying to prevent that. Any insights on my problem?

EDIT: lives here for now: http://5f6738d9.ngrok.io/test/public/index.html username and password are test

Community
  • 1
  • 1
Lagastic
  • 93
  • 1
  • 11
  • Check developers console – u_mulder Jul 05 '15 at 15:45
  • It does not say anything except 'navigated to:' – Lagastic Jul 05 '15 at 15:49
  • 1
    Sounds like a conflict with the jQuery library not loading. Can you ensure it's loading? – Ohgodwhy Jul 05 '15 at 15:52
  • Jquery is loaded. Tested with this code window.onload = function() { if (window.jQuery) { // jQuery is loaded alert("Yeah!"); } else { // jQuery is not loaded alert("Doesn't Work"); } } – Lagastic Jul 05 '15 at 15:55
  • This might be a bit to obvious, but did you make sure your code is inside `$(document).ready(function(){..`? – icecub Jul 05 '15 at 16:05
  • 1
    Here's a [jsfiddle](https://jsfiddle.net/gLd5ymr9/) demo with the code you posted, and configured with jQuery 1.11.0 - there's no problem there, it works. I've modified the two `input` fields to have closing backslashes before the last `>`. Seems like it might be something beyond what we can see in your question. – Ross Jul 05 '15 at 16:06
  • Yes it is inside of it. – Lagastic Jul 05 '15 at 16:09
  • @Ross — "I've modified the two input fields to have closing backslashes before the last >" — It isn't XML, that's pointless. – Quentin Jul 05 '15 at 16:27
  • @Quentin So? I was just clarifying what I had modified - which was as a result of jsfiddle red flagging the original html. Humble apologies if that offended you. – Ross Jul 05 '15 at 16:35

3 Answers3

0

Your submit button is a standard submit type button which means that your form will be submitted normally. Based on your HTML code it will just submit the form to the same URL. The JS code will not have time to execute. All you need to do is cancel de default HTML form submit by adding

event.preventDefault();

You need to add this first thing in your submit listener. So your JS code will start like this

$("#AjaxForm").submit(function(event){
    event.preventDefault();
    // Abort any pending request
    if (request) {
        request.abort();
    }
    //....

Try using the following code:

$(document).ready(function(){
    $('#AjaxForm').on('submit', function(event){
        event.preventDefault();

        if(request){
            request.abort();
            request = false;
        }

        var $form = $(this);
        var serializedData = $form.serialize();
        var $inputs = $form.find("input, select, button, textarea");
        $inputs.prop("disabled", true);

        var request = $.ajax({
            url: 'login.php',
            type: 'POST',
            data: serializedData,
            success: function (data, textStatus, jqXHR) {
                // login was successful so maybe refresh the page
                window.location.reload();
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // display form errors received from server
            },
            complete: function (jqXHR, textStatus) {
                request = false;
            }
        });
    });
});
Ovidiu D.
  • 106
  • 4
  • So.. what exactly do you think `request.abort();` is doing...? – icecub Jul 05 '15 at 16:07
  • 1
    In case somebody clicks more then one time on the submit button the script will end up sending the request many time. The abort() can be used to stop the current AJAX request. So when you first click the submit the AJAX request will be stored in the request variable. Then if you click the button again while the AJAX is still in progress it will just abort it and start a new one. – Ovidiu D. Jul 05 '15 at 16:10
  • Also be aware that request.done() is called on success or failure...so it doesn't mean the that the login was successful. You should use request.success() for successful login, request.error() for failure. Also you should delete the set the request variable to false as soon as the request is completed. Otherwise in case of an error the user will not be able to submit the form again. – Ovidiu D. Jul 05 '15 at 16:11
  • 1
    I tried as you said and it doesn't work, but i've tried putting console.log('1'); above the event.preventDefault(); and it also doesn't log to the console so i think it's a problem with the whole code no executing – Lagastic Jul 05 '15 at 16:13
0

Check that the event is bound within a $(document).on('ready' ... otherwise the event won't fire and the form will just submit normally or not via AJAX.

Your code should look like:

$(document).on('ready', function () {
    var request;
    $("#AjaxForm").submit(function(event){

    // Abort any pending request
    if (request) {
        request.abort();
    }
    // setup some local variables
    var $form = $(this);

    // Let's select and cache all the fields
    var $inputs = $form.find("input, select, button, textarea");

    // Serialize the data in the form
    var serializedData = $form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    $inputs.prop("disabled", true);

    // Fire off the request to /form.php
    request = $.ajax({
        url: "login.php",
        type: "post",
        data: serializedData
    });

    // Callback handler that will be called on success
    request.done(function (response, textStatus, jqXHR){
        // Log a message to the console
        console.log("Hooray, it worked!");
    });

    // Callback handler that will be called on failure
    request.fail(function (jqXHR, textStatus, errorThrown){
        // Log the error to the console
        console.error(
            "The following error occurred: "+
            textStatus, errorThrown
        );
    });

    // Callback handler that will be called regardless
    // if the request failed or succeeded
    request.always(function () {
        // Reenable the inputs
        $inputs.prop("disabled", false);
    });

    // Prevent default posting of form
    event.preventDefault();
  });
});

Note that these callback events are actually deprecated as of jQuery 1.8.

You will also need to ensure that your POST and action attributes are set on the form in all cases.

Daniel Waghorn
  • 2,997
  • 2
  • 20
  • 33
  • I guess its answer because I tried to exec script in question, (include jQuery, form, script) and it was fine for me, i got `Hooray, it worked!` – Sergey Chizhik Jul 05 '15 at 16:10
  • Used this and it does login but it doesn't use ajax because when i comment the ajax out it also submits. And i don't get an alert. Take a look: http://5f6738d9.ngrok.io/test/public/index.html username is test and password is test – Lagastic Jul 05 '15 at 16:24
  • Where exactly in your source / js files have you got the AJAX code? – Daniel Waghorn Jul 05 '15 at 16:34
  • In the html page for now in – Lagastic Jul 05 '15 at 16:38
0

Personally I would use this instead:

$(document).ready(function(){
    $("#AjaxForm").on("submit",function(e){
        e.preventDefault();

        var $form = $(this);
        var $cacheData = $form.find("input, submit");
        var serializedData = $form.serialize();

        $.ajax({
            url: $form.attr("action"),
            type: $form.attr("method"),
            data: serializedData,
            xhrFields: {
                onprogress: function(e){
                    $cacheData.prop("disabled", true);
                    console.log(e.loaded / e.total*100 + "%");
                }
            },
            done: function(text){
                if(text == "Succes!"){
                    alert(text);
                } else {
                    alert(text);
                }
            },
            fail: function(xhr, textStatus, errorThrown){
                alert(textStatus + " | " + errorThrown);
            },
            always: function(){
                $cacheData.prop("disabled", false);
            }
        });
    });
});

This allows you to do some usefull things:

  1. You're able to monitor the progress in the console
  2. Just because Ajax is succesfull, doesn't mean you can't have an error returned. For example: Wrong password. So now you can simple echo errors back this script will show them. Echo "Succes!" when the login was fine.

Keep in mind though that this script requires that you set the HTML attributes action and method in your form.

icecub
  • 8,615
  • 6
  • 41
  • 70
  • I don't mind if you downvote my answer. But please explain why so it can be improved. – icecub Jul 05 '15 at 16:32
  • I think they did because you are using the deprecated succes and error? I'm not sure but from what i've read i think it's best to use .done .fail and .always now. – Lagastic Jul 05 '15 at 16:36
  • @Lagastic Hmm although that might be it, according to http://api.jquery.com/jquery.ajax/ neither are deprecated. Not even an advise to use something different? – icecub Jul 05 '15 at 16:40
  • @icecub while I wouldn't downvote anyone (because I have better things to do in life!), there is a yellow box a ways down that page you linked which mentions the deprecation as of jQuery 1.8 for jqXHR.success / error / complete. – Ross Jul 05 '15 at 16:46
  • @Ross Thanks! It seems I've missed it. Updated my answer accordingly. – icecub Jul 05 '15 at 16:50