Dalton
Dalton

Reputation: 137

.preventDefault() is not working in conditionals

I have a bit of a problem. When a form is submitted, I wan't to check some things about it, and if something is wrong, I want to prevent it from submitting and then show an error on the client side. Everything seems to work fine except the form keeps submitting. It even shows the error on client side for a split second before it submits.

$('#register').on('submit', function (e) {
e.preventDefault();

var username = $("#register-username"),
    name = $("#register-name"),
    email = $("#register-email"),
    password = $("#register-password"),
    confirmPassword = $("#register-confirmPassword");

checkUsername(function (res) {
    if (res) {
        checkEmail(function (res) {
            if (res) {
                this.submit();
            } else {
                clearErrors();
                email.toggleClass('input-error');
            }
        });
    } else {
        clearErrors();
        username.toggleClass('input-error');
    }
});
});



function checkEmail(callback) {
  $.get("/checkEmail/" + $('#register-email').val(), function (data) {
      if ( data == undefined ) {
        callback(true);
      } else {
        callback(false);
      }
  });
}

function checkUsername (callback) {
  $.get("/checkUsername/" + $('#register-username').val(), function (data) {
    if ( data == undefined ) {
        callback(true);
    } else {
        callback(false);
    }
  });
}

function clearErrors () {
  var arr = [
    $("#register-username"),
    $("#register-name"),
    $("#register-email"),
    $("#register-password"),
    $("#register-confirmPassword")
  ];

  arr.forEach(function(el) {
    el.removeClass('input-error');
  });
}

Update: Now I am just confusing myself. checkUsername() returns undefined from my server, I know for a fact, but somehow it is reaching the 'else' statement where checkUsername() is called. I've added the rest of my code. Should clear some confusion.

Upvotes: 0

Views: 94

Answers (4)

Dalton
Dalton

Reputation: 137

So I built off of charlietfl's solution and assigned the native form to a variable, and then submitted it within an anon function.

$('#register').on('submit', function (e) {
  e.preventDefault()
  var username = $("#register-username"),
    name = $("#register-name"),
    email = $("#register-email"),
    password = $("#register-password"),
    confirmPassword = $("#register-confirmPassword"),
    form = document.getElementById('register');



  $.get("/checkUsername/" + username.val(), function (data) {
     if (data) {
        clearErrors();
        username.toggleClass('input-error');
     } else {
        $.get("/checkEmail/" + email.val(), function (data) {
            if ( data ) {
                clearErrors();
                email.toggleClass('input-error');
            } else {
                form.submit();
            }
        });
     }
  });
});

This works.

Upvotes: 0

Saqib Rokadia
Saqib Rokadia

Reputation: 649

You need to return false from validation to stop the current submitting event, and then manually send the post request on success from when the callbacks have successfully returned.

Since the callback is running after the validation has returned from the server then you can actually affect whether a request is made. Where as the other solutions involve trying to change how the original submit event occurs which is no longer in scope since you've already sent requests to the server at this point.

$('#register').on('submit', function (e) {

    var username = $("#register-username"),
        name = $("#register-name"),
        email = $("#register-email"),
        password = $("#register-password"),
        confirmPassword = $("#register-confirmPassword");

    checkUsername(function (res) {
        if (res) {
            checkEmail(function (res) {
                if (res) {
                    $.post('{insert form action here}', $(this).serialize());
                } else {
                    clearErrors();
                    email.toggleClass('input-error');
                }
            });
        } else {
            clearErrors();
            username.toggleClass('input-error');
        }
    });

    return false;
});

You'll have to replace the {insert form action here}, and $(this).action might work in it's place, but I'm not sure.

Upvotes: 0

charlietfl
charlietfl

Reputation: 171690

Assuming the problem is due to asynchronous code not shown, an effective way is to use preventDefault for the jQuery submit handler and use native submit when all validation passes

Something like:

$('#register').on('submit', function (e) {
    e.preventDefault();// prevent jQuery submit

    // after all validation passes
    this.submit();// submit native method won't trigger jQuery handler again

})

Upvotes: 1

Jack A.
Jack A.

Reputation: 4453

The call to preventDefault is made from the anonymous callback function you're passing to checkUsername. If the anonymous function is called asynchronously, then it's too late to cancel the event.

Upvotes: 5

Related Questions