8

I need to validate my form using JavaScript because iPhone / Safari do not recognize the required attribute. I want individual error messages to appear below each empty input field.

My code works, but the individual error message does not disappear when the field is filled in. Also, I would like all messages to appear initially, for all empty fields (not one by one). I am very very new to JavaScript, sorry.

My HTML:

<form onsubmit="return validateForm()" method="post" action="form.php" name="english_registration_form" id="english_registration_form">
        <input type="text" id="name" name="name" aria-describedby="name-format" required placeholder="Name">
        <span class="error"><p id="name_error"></p></span>
        <input type="email" id="email" name="email" required placeholder="Email">
        <span class="error"><p id="email_error"></p></span>
        <input type="tel" id="telephone" name="telephone" required placeholder="Telephone">
        <span class="error"><p id="telephone_error"></p></span>
        <button class="register_button" type="submit" value="submit">Register Now</button>
    </form>

And my JavaScript:

<script>
function validateForm() {
var x = document.forms["english_registration_form"]["name"].value;
var y = document.forms["english_registration_form"]["email"].value;
var z = document.forms["english_registration_form"]["telephone"].value;

if (x == null || x == "") {
    nameError = "Please enter your name";
    document.getElementById("name_error").innerHTML = nameError; 
    return false;
} 

else if (y == null || y == "") {
    emailError = "Please enter your email";
    document.getElementById("email_error").innerHTML = emailError;
    return false;
} 

else if (z == null || z == "") {        
    telephoneError = "Please enter your telephone";
    document.getElementById("telephone_error").innerHTML = telephoneError;
    return false;
} 

else {return true;}
}
</script>

Thanks for your help.

Maximillian Laumeister
  • 19,884
  • 8
  • 59
  • 78
Sophie
  • 83
  • 1
  • 1
  • 6
  • In my opinion you can put the errors strings hard-coded in the HTML error spans with style="display:none;" (hide them), and then, when needed - show them (remove the above style for relevant span). Next, add this function to 'onchange' event rather than on submit – ItayB Sep 22 '15 at 04:23

4 Answers4

9

Here is a solution that displays all relevant errors when the form is first submitted, and removes an error when the user modifies text in the relevant input element.

To get it to display all of the errors on first run, I used if statements instead of if else, and used a flag to determine whether the form should be submitted. To remove the warnings when the input is modified, I bound the onkeyup events of the inputs.

I ended up removing the required attributes on the inputs so that the demonstration will work in a modern browser that supports them.

Live Demo:

document.getElementById("english_registration_form").onsubmit = function () {
    var x = document.forms["english_registration_form"]["name"].value;
    var y = document.forms["english_registration_form"]["email"].value;
    var z = document.forms["english_registration_form"]["telephone"].value;

    var submit = true;

    if (x == null || x == "") {
        nameError = "Please enter your name";
        document.getElementById("name_error").innerHTML = nameError;
        submit = false;
    }

    if (y == null || y == "") {
        emailError = "Please enter your email";
        document.getElementById("email_error").innerHTML = emailError;
        submit = false;
    }

    if (z == null || z == "") {
        telephoneError = "Please enter your telephone";
        document.getElementById("telephone_error").innerHTML = telephoneError;
        submit = false;
    }

    return submit;
}

function removeWarning() {
    document.getElementById(this.id + "_error").innerHTML = "";
}

document.getElementById("name").onkeyup = removeWarning;
document.getElementById("email").onkeyup = removeWarning;
document.getElementById("telephone").onkeyup = removeWarning;
<form method="post" action="form.php" name="english_registration_form" id="english_registration_form">
    <input type="text" id="name" name="name" aria-describedby="name-format" placeholder="Name"> <span class="error"><p id="name_error"></p></span>

    <input type="email" id="email" name="email" placeholder="Email"> <span class="error"><p id="email_error"></p></span>

    <input type="tel" id="telephone" name="telephone" placeholder="Telephone"> <span class="error"><p id="telephone_error"></p></span>

    <button class="register_button" type="submit" value="submit">Register Now</button>
</form>

JSFiddle Version: https://jsfiddle.net/xga2shec/

Maximillian Laumeister
  • 19,884
  • 8
  • 59
  • 78
  • I'm not sure what I am doing wrong. I copied your code in the script tags in the head of my HTML document but this did not work. It submitted the form without warning me the fields were empty. – Sophie Sep 23 '15 at 03:33
  • 1
    @Sophie [It's recommended](http://stackoverflow.com/a/10994391/2234742) to instead place your scripts at the end of the `` tag of your HTML. If you need to put them in the ``, then you will need to wrap the script in `document.addEventListener('DOMContentLoaded', function () { /* all code goes here */ }`. This needs to be done because the JavaScript needs to run after the document is parsed (because it modifies elements in the document), so if the script is in the `` instead of body, we need to delay it until the rest of the document is parsed by using `DOMContentLoaded`. – Maximillian Laumeister Sep 23 '15 at 03:43
  • @Sophie And if it's still not working after that change (either moving your scripts to the end of `` or adding the event listener), please post the errors that come up in the JavaScript console. Thanks! – Maximillian Laumeister Sep 23 '15 at 03:44
  • Of course! Thanks so much for replying so quickly. This works :) – Sophie Sep 23 '15 at 03:52
  • Hi @MaximillianLaumeister, if I have a second form on the same page with the ID contact_form and with the fields Name, Email, Phone and Message, and all fields are also required, should I just duplicate the script and make minor amendments, or is there a way to have only once script for both? – Sophie Sep 25 '15 at 00:57
  • 1
    @Sophie It would be possible to have one script for both, but it would involve refactoring the code quite a bit. If you are looking for a short-term solution I would just duplicate it, but if you are looking for the most elegant solution, then I would modify the current script (if you need help you can ask another SO question.) – Maximillian Laumeister Sep 25 '15 at 01:01
2

First of all, we change your function validateForm so it can handle multiple validations.

Then, we create a DOMContentLoaded event handler on the document, and we call the validateForm function, so we validate the field when the page is loaded.

And to finish, we create input event handlers on the inputs, so everytime someone change any data inside them, the form is validated again.

Take a look at the code commented, and see the working version in action!

function validateForm() {
  var valid = true; // creates a boolean variable to return if the form's valid
  
  if (!validateField(this, 'name')) // validates the name
    valid = false;
  
  if (!validateField(this, 'email')) // validates the email (look that we're not using else if)
    valid = false;
  
  if (!validateField(this, 'telephone')) // validates the telephone 
    valid = false;
  
  return valid; // if all the fields are valid, this variable will be true
}

function validateField(context, fieldName) { // function to dynamically validates a field by its name
  var field = document.forms['english_registration_form'][fieldName], // gets the field
      msg = 'Please enter your ' + fieldName, // dynamic message
      errorField = document.getElementById(fieldName + '_error'); // gets the error field
console.log(context);
  // if the context is the form, it's because the Register Now button was clicked, if not, check the caller
  if (context instanceof HTMLFormElement || context.id === fieldName)
    errorField.innerHTML = (field.value === '') ? msg : '';

  return field.value !== ''; // return if the field is fulfilled
}


document.addEventListener('DOMContentLoaded', function() { // when the DOM is ready
  // add event handlers when changing the fields' value
  document.getElementById('name').addEventListener('input', validateForm);
  document.getElementById('email').addEventListener('input', validateForm);
  document.getElementById('telephone').addEventListener('input', validateForm);
  
  // add the event handler for the submit event
  document.getElementById('english_registration_form').addEventListener('submit', validateForm);
});
<form method="post" action="form.php" name="english_registration_form" id="english_registration_form">
  <input type="text" id="name" name="name" aria-describedby="name-format" required placeholder="Name">
  <span class="error"><p id="name_error"></p></span>
  <input type="email" id="email" name="email" required placeholder="Email">
  <span class="error"><p id="email_error"></p></span>
  <input type="tel" id="telephone" name="telephone" required placeholder="Telephone">
  <span class="error"><p id="telephone_error"></p></span>
  <button class="register_button" type="submit" value="submit">Register Now</button>
</form>
Buzinas
  • 11,597
  • 2
  • 36
  • 58
  • Hi, thanks for this. This is great, but it shows the warnings straight away. Because this form will be on a page where registration is not compulsory, it would be nice if the errors only appeared as the user clicks "register now". – Sophie Sep 23 '15 at 03:38
  • 1
    @Sophie I thought that was the desired result, when I've read " Also, I would like all messages to appear initially, for all empty fields (not one by one)". I've edited my answer, so it doesn't validate when the page loads. – Buzinas Sep 23 '15 at 03:41
  • Hi Buzinas, sorry my question was not clear. You are right, I should have said "I would like all error messages to appear at once when the submit button is pressed, as opposed to one field at a time". Thanks for replying so quickly! – Sophie Sep 23 '15 at 03:46
  • 1
    @Sophie if my answer was useful for you, please click on the arrow to upvote it, and on the `V` to accept it as the accepted answer. Thank you! :) – Buzinas Sep 23 '15 at 03:52
  • Hi Buzinas, I did upvote it :). I kept clicking back and forth between your post and @MaximillianLaumeister as the accepted answer as there can only be one. In the end I chose his (Sorry!) simply because it was easier to understand and because it allowed for full customisation of each error message. Really appreciate your help though! – Sophie Sep 23 '15 at 23:23
0

you have to use style.display="none" to hide error and style.display="block" to show error

 <script>
    function validateForm() {
    var x = document.forms["english_registration_form"]["name"].value;
    var y = document.forms["english_registration_form"]["email"].value;
    var z = document.forms["english_registration_form"]["telephone"].value;

    if (x == null || x == "") {
        nameError = "Please enter your name";
document.getElementById("name_error").style.display="block";
        document.getElementById("name_error").innerHTML = nameError; 
        return false;
    } 
    else if (x != null || x != "") {
        nameError = "Please enter your name";
        document.getElementById("name_error").style.display="none"; 
        return false;
    } 

     if (y == null || y == "") {
        emailError = "Please enter your email";
 document.getElementById("email_error").style.display="block"; 
        document.getElementById("email_error").innerHTML = emailError;
        return false;
    } 
    else if (y != null || y != "") {
        emailError = "Please enter your email";
        document.getElementById("email_error").style.display="none"; 
        return false;
    } 

     if (z == null || z == "") {        
        telephoneError = "Please enter your telephone";
 document.getElementById("telephone_error").style.display="block"; 
        document.getElementById("telephone_error").innerHTML = telephoneError;
        return false;
    } 

     else if (z != null || z != "") {        
        telephoneError = "Please enter your telephone";
        document.getElementById("telephone_error").style.display="none"; 
        return false;
    } 

    else {return true;}
    }
    </script>
kavinhuh
  • 739
  • 1
  • 9
  • 30
0

function validateForm() {
  var valid = true; // creates a boolean variable to return if the form's valid
  
  if (!validateField(this, 'name')) // validates the name
    valid = false;
  
  if (!validateField(this, 'email')) // validates the email (look that we're not using else if)
    valid = false;
  
  if (!validateField(this, 'telephone')) // validates the telephone 
    valid = false;
  
  return valid; // if all the fields are valid, this variable will be true
}

function validateField(context, fieldName) { // function to dynamically validates a field by its name
  var field = document.forms['english_registration_form'][fieldName], // gets the field
      msg = 'Please enter your ' + fieldName, // dynamic message
      errorField = document.getElementById(fieldName + '_error'); // gets the error field
console.log(context);
  // if the context is the form, it's because the Register Now button was clicked, if not, check the caller
  if (context instanceof HTMLFormElement || context.id === fieldName)
    errorField.innerHTML = (field.value === '') ? msg : '';

  return field.value !== ''; // return if the field is fulfilled
}


document.addEventListener('DOMContentLoaded', function() { // when the DOM is ready
  // add event handlers when changing the fields' value
  document.getElementById('name').addEventListener('input', validateForm);
  document.getElementById('email').addEventListener('input', validateForm);
  document.getElementById('telephone').addEventListener('input', validateForm);
  
  // add the event handler for the submit event
  document.getElementById('english_registration_form').addEventListener('submit', validateForm);
});
<form method="post" action="form.php" name="english_registration_form" id="english_registration_form">
  <input type="text" id="name" name="name" aria-describedby="name-format" required placeholder="Name">
  <span class="error"><p id="name_error"></p></span>
  <input type="email" id="email" name="email" required placeholder="Email">
  <span class="error"><p id="email_error"></p></span>
  <input type="tel" id="telephone" name="telephone" required placeholder="Telephone">
  <span class="error"><p id="telephone_error"></p></span>
  <button class="register_button" type="submit" value="submit">Register Now</button>
</form>
jvk
  • 2,133
  • 3
  • 19
  • 28