skip to Main Content

In my snippet below you can see that I have a form where I wish to only enable the submit button after all input fields are correctly filled out.

I do this by adding a change event listener to the form itself and then calling the checkValidity() function on the inputs inside the form. (in this example I have only 1) If all the checkValidity() checks return true, I enable the button, if not I disable it.

However, I noticed that calling checkValidity() this also triggers the invalid event listener when the input is invalid which is not desireable. I am using the invalid event listener for other stuff like if the form gets submitted anyways via keyboard shortcuts or other means so I can display an appropriate error message for the input fields because the submit call also will check the validity and trigger the invalid event.

So is there a way to check the validity of the input without triggering the invalid event so I can keep my invalid event listener and not have to write a custom validity check function for every single input?

const form = document.getElementById("form");
const input = document.getElementById("input");
const button = document.getElementById("button");
const checkbox = document.getElementById("checkbox");

form.addEventListener("change", () => {
    if (!checkbox.checked) return;
    if (input.checkValidity()) {
        button.removeAttribute("disabled");
    } else {
        button.setAttribute("disabled", "");
    }
})

input.addEventListener("invalid", (e) => {
    e.preventDefault();
    console.log("Invalid");
});

form.addEventListener("submit", (e) => {
    e.preventDefault();
    console.log("submitted!");
});
button[disabled] {
    opacity: 0.5;
}
<form id="form">
  <input type="text" id="input" minLength="5">
  <button type="submit" id="button" disabled>Submit</button>
</form>
<br>
<label>
  <span>turn on change listener</span>
  <input type="checkbox" id="checkbox" checked>
</label>

2

Answers


  1. Using input.validity.valid allows you to check the validity of the input without triggering the invalid event, thus keeping your existing invalid event listener functional for other scenarios like form submission attempts. hope this might help out

    form.addEventListener("change", () => {
        if (!checkbox.checked) return;
        if (input.validity.valid) {
            button.removeAttribute("disabled");
        } else {
            button.setAttribute("disabled", "");
        }
    });
    
    Login or Signup to reply.
  2. I don’t know if you will find this useful, but on the invalid event you could test if it was the submit button that was clicked (and then do stuff in that case). Then you can still use checkValidity() in the input callback, because the e.explicitOriginalTarget in that case is the input element.

    const form = document.forms["form"];
    
    form.addEventListener("invalid", (e) => {
      e.preventDefault();
      // test if is was the submit button that was clicked
      if (e.explicitOriginalTarget == e.target.form.button) {
        console.log(e.target.name, "is invalid");
      }
    }, true);
    
    form.addEventListener("input", (e) => {
      let formvalid = e.target.form.checkValidity();
      e.target.form.button.disabled = !formvalid;
    });
    
    form.addEventListener("submit", (e) => {
      e.preventDefault();
      console.log("submitted!");
    });
    button[disabled] {
      opacity: 0.5;
    }
    <form id="form">
      <input type="text" name="input1" minLength="5" required>
      <input type="text" name="input2" minLength="5" required>
      <button type="submit" name="button" disabled>Submit</button>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search