0

I was trying to create an html form.
I was filling up and validating the form with javascript. I also created an error label for each field.
To do this, I created an object form_fields that contains the field name, as well as the input element, error element, and the corresponding validate function.
The input_field and error_field of each field is set while filling the form.
My code:

const form_fields = {
    name : { validate: validate_name },
    roll : { validate: validate_roll }
};

const form = document.getElementById("student_data");
function fill_form() {
    for(const [field, data] of Object.entries(form_fields)) {
        form.innerHTML += `
        <label for="${field}_field">Enter your ${field}: </label><br>
        <input type="text" id="${field}_field" name="${field}_field">
        <label style="color: red;" id="${field}_error_label">*</label><br>
        `;
        data.input_field = document.getElementById(field + "_field");
        data.error_field = document.getElementById(field + "_error_label");
        console.log(field, data.input_field, data.error_field);
    }
    form.innerHTML += '<button type="submit">Submit</button>';
}

function validate_name(name, error_field) {
    console.log(name);
    if(name == "") {
        error_field.innerHTML = "Name is required.";
        return true;
    }
}

function validate_roll(roll, error_field) {
    if(roll == "") {
        error_field.innerHTML = "Roll number is required.";
        return true;
    }
    else if(! new RegExp("^19HCS40[0-9]{2}$").test(roll)) {
        error_field.innerHTML = "Provided roll number is not correct.";
        return true;
    }
}

function validate() {
    let error_occurred = false;

    console.log(form_fields.roll.error_field);
    error_occurred = validate_roll('', form_fields.roll.error_field);
    console.log(error_occurred);

    return false;//!error_occurred;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Some Task</title>
</head>
<body onload="fill_form()">
    <form id="student_data" onsubmit="return validate()"></form>
    <!--<script src="validate.js"></script>-->
</body>
</html>

When I ran the line error_occurred = validate_roll('', form_fields.roll.error_field);, I expected it would set the error label and return true.
But, for some reason, the label is not set, even though the validate_roll function returns true.
An even more interesting thing was that the console was saying the error was set!

name <input type=​"text" id=​"name_field" name=​"name_field">​ <label style=​"color:​ red;​" id=​"name_error_label">​*​</label>​ validate.js:15 
roll <input type=​"text" id=​"roll_field" name=​"roll_field">​ <label style=​"color:​ red;​" id=​"roll_error_label">​*​</label> validate.js:43 
<label style=​"color:​ red;​" id=​"roll_error_label">​Roll number is required.​</label>​                                     validate.js:45 
true

What am I doing wrong here?

1 Answer 1

1

The problem comes from the way you construct your form. When you do form.innerHTML += … you don't add code, you overwrite the whole code. As a result, when your form is completed, the elements stored in input_field and error_field of the form_fields object are not the same as the ones in your form final code.

One way to fix that, is to assign input_field and error_field properties after the form as heen created (see the snippet below).

Another option would be to remove input_field and error_field as well as the second parameter of validate_* function and get the element by id inside the respective function.

const form_fields = {
  name: {
    validate: validate_name
  },
  roll: {
    validate: validate_roll
  }
};

const form = document.getElementById("student_data");

function fill_form() {
  for (const [field, data] of Object.entries(form_fields)) {
    form.innerHTML += `
        <label for="${field}_field">Enter your ${field}: </label><br>
        <input type="text" id="${field}_field" name="${field}_field">
        <label style="color: red;" id="${field}_error_label">*</label><br>
        `;
  }
  form.innerHTML += '<button type="submit">Submit</button>';
  
  for (const [field, data] of Object.entries(form_fields)) {
    data.input_field = document.getElementById(field + "_field");
    data.error_field = document.getElementById(field + "_error_label");
    console.log(field, data.input_field, data.error_field);
  }
}

function validate_name(name, error_field) {
  console.log(name);
  if (name == "") {
    error_field.innerHTML = "Name is required.";
    return true;
  }
}

function validate_roll(roll, error_field) {
  if (roll == "") {
    error_field.innerHTML = "Roll number is required.";
    return true;
  } else if (!new RegExp("^19HCS40[0-9]{2}$").test(roll)) {
    error_field.innerHTML = "Provided roll number is not correct.";
    return true;
  }
}

function validate() {

    // this way all the validate_* function are executed  
  const error_occurred = [
      validate_roll('', form_fields.roll.error_field),
      validate_name('', form_fields.name.error_field)
  ].some(error => error);
  
  console.log(error_occurred);

  return false; //!error_occurred;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Some Task</title>
</head>
<body onload="fill_form()">
    <form id="student_data" onsubmit="return validate()"></form>
    <!--<script src="validate.js"></script>-->
</body>
</html>

Sign up to request clarification or add additional context in comments.

2 Comments

Hey, thanks for your answer. But, even when I put valid input, the error labels are set to Name is required and Roll number is required.
Did you change the validate_* functions ? So far you're calling validate_roll('', form_fields.roll.error_field), which means whatever is in the input you always call the function with '' (an empty string) hence the error message. Try instead validate_roll(form_fields.roll.input_field.value, form_fields.roll.error_field) and, of course same goes for validate_name

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.