Individual error messages for empty form fields using JavaScript

59,113

Solution 1

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/

Solution 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>
Share:
59,113
Sophie
Author by

Sophie

Updated on July 20, 2022

Comments

  • Sophie
    Sophie almost 2 years

    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.

  • Sophie
    Sophie over 8 years
    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
    Sophie over 8 years
    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".
  • Buzinas
    Buzinas over 8 years
    @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.
  • Maximillian Laumeister
    Maximillian Laumeister over 8 years
    @Sophie It's recommended to instead place your scripts at the end of the <body> tag of your HTML. If you need to put them in the <head>, 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 <head> instead of body, we need to delay it until the rest of the document is parsed by using DOMContentLoaded.
  • Maximillian Laumeister
    Maximillian Laumeister over 8 years
    @Sophie And if it's still not working after that change (either moving your scripts to the end of <body> or adding the event listener), please post the errors that come up in the JavaScript console. Thanks!
  • Sophie
    Sophie over 8 years
    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
    Sophie over 8 years
    Of course! Thanks so much for replying so quickly. This works :)
  • Buzinas
    Buzinas over 8 years
    @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! :)
  • Sophie
    Sophie over 8 years
    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
    Sophie over 8 years
    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?
  • Maximillian Laumeister
    Maximillian Laumeister over 8 years
    @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.)