J. Brink
J. Brink

Reputation: 99

onsubmit returns false, but submit executes anyway

I'm lost again. I have a registration form with three JS functions that produce the desired output when called by onchange from my html form. So they produce a BS alert while the user is filling out the form. These are the three functions:

To check password length:

function checkPassword() {
    var x = document.registerForm;
    var wachtwoord = x.wachtwoord.value;
    var errMsgHolder = document.getElementById("message");
    if (wachtwoord.length < 3 || wachtwoord.length >30) {
        errMsgHolder.innerHTML =
            '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Kies een wachtwoord van minimaal 3 en maximaal 30 tekens.</div>';
        setTimeout(function () {document.getElementById("message").innerHTML =''; }, 5000);
        return false;
    }
}

To check if the 2 passwords match:

function checkPasswordsMatch() {
    var x = document.registerForm;
    var wachtwoord = x.wachtwoord.value;
    var herhaal_wachtwoord = x.herhaal_wachtwoord.value;
    var errMsgHolder = document.getElementById("message");
    if (wachtwoord !== herhaal_wachtwoord) {
        errMsgHolder.innerHTML =
            '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Wachtwoorden komen niet overeen.</div>';
            return false;
    }
}

To check if username already exists (ajax call via php to database):

function checkBestaandeGebruikersnaam(){
var x = document.registerForm;
var gebruikersnaam = x.gebruikersnaam.value;
var errMsgHolder = document.getElementById("message");
var request = new XMLHttpRequest();

request.onreadystatechange = function() {
  if(request.readyState === 4 && request.status === 200) { 
      if(request.responseText == "1") {
            errMsgHolder.innerHTML = '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Die gebruikersnaam is al bezet, kies een andere gebruikersnaam.</div>';
      return false;
      }
      else {
          errMsgHolder.innerHTML = '';
      }
    } else {
      errMsgHolder.innerHTML = 'An error occurred during your request: ' +  request.status + ' ' + request.statusText;
    } 
  }
request.open("POST", "core/functions/checkBestaandeGebruikersnaam.php", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send("gebruikersnaam="+gebruikersnaam);  
}

But these functions just show an alert and don't prevent a user from submitting a form with incorrect data. So I want to revisit these functions when the user submits. To do that I have the following line in my HTML register form:

<form action="register.php" onsubmit="return validate()" name="registerForm" method="post" class="col-md-10 col-md-offset-1 col-xs-12 col-xs-offset-0">

Then in JS I have the following function:

function validate() {
var errMsgHolder = document.getElementById("message");
if(checkPassword() === false ) {
    errMsgHolder.innerHTML =
            '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Kies een wachtwoord van minimaal 3 en maximaal 30 tekens.</div>';
            return false;
} else if(checkPasswordsMatch() === false){
    errMsgHolder.innerHTML =
            '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Wachtwoorden komen niet overeen.</div>';
            return false;
} else if(checkBestaandeGebruikersnaam() === false){
    errMsgHolder.innerHTML = 
            '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Die gebruikersnaam is al bezet, kies een andere gebruikersnaam.</div>';
            return false;
}

When I test this it works for checkPassword() and checkPasswordsMatch(). Meaning I get the expected BS alerts and the submission of the form is cancelled. But when I test the checkBestaandeGebruikersnaam() it does not. It briefly shows the BS alert, but then it continues to my register.php file. So for some reason it disregards the returned 'false' in onsubmit and submits anyway.

I can't get my head around it. Why is it doing this one differently. Can anyone shed some light on the issue?

Edit: I have followed the link and spent the rest of the day trying to grasp the concept of callback functions. I think I have it now, but my problem is not solved. So I must still be doing something wrong.

Since the problem is obviously with the way I return false from the function checkBestaandeGebruikersnaam() I will only list the changes to that function. I have the following code now:

HTML:

onchange="callAjax(checkBestaandeGebruikersnaam)"

JavaScript main function:

function callAjax(callback){
var gebruikersnaam = document.registerForm.gebruikersnaam.value;
var request = new XMLHttpRequest();

request.onreadystatechange = function() {
  if(request.readyState === 4 && request.status === 200) { 
        callback(request.responseText);
    } else {
        document.getElementById("message").innerHTML = 'An error occurred during your request: ' +  request.status + ' ' + request.statusText;
    } 
  }
request.open("POST", "core/functions/checkBestaandeGebruikersnaam.php", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send("gebruikersnaam="+gebruikersnaam); 
}

JavaScript callback function:

function checkBestaandeGebruikersnaam(result) {
if(result == "1") {
    document.getElementById("message").innerHTML = '<div class="alert alert-warning"><a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Let op!</strong> Die gebruikersnaam is al bezet, kies een andere gebruikersnaam.</div>';
    return false;
}
else {
    document.getElementById("message").innerHTML = '';
}
}

Can someone tell me if I am using the callback functionality correctly? It does perform as expected (on the onchange event).

The function validate() still doesn't work for checkBestaandeGebruikersnaam() though. It still executes, even if checkBestaandeGebruikersnaam() === false. What have I done wrong now? Please enlighten me and thanks for your time.

Upvotes: 0

Views: 811

Answers (2)

flatline
flatline

Reputation: 42613

checkBestaandeGebruikersnaam never returns false. The onreadystatechange callback function does, but that is executed asynchronously. So checkBestaandeGebruikersnaam executes and returns (an undefined value) immediately and the return false; that you seem to be expecting happens sometime later and is ignored. Matteo suggested a link for returning the response from an asynchronous call, which you should check out, it is on the right track to solving your problem. In modern JavaScript I would suggest handling this with a Promise chain.

Another way to solve this would be to explicitly submit the form from javascript whenever the required conditions pass - e.g. from within the onreadystatechange method, so you don't have to worry about the asynchronous state control. The form element has a submit method you can call.

Upvotes: 1

Affan Pathan
Affan Pathan

Reputation: 308

I think you need to remove the onsubmit property of the form, and instead use the Submit button's onclick property:

onclick="return validate();"

This would work. Thanks!

Upvotes: 0

Related Questions