简体   繁体   中英

Disable submit button when all fields are filled (pure javascript)

Found lots of answers for this in jQuery, but I want to do it in pure Javascript. This code doesn't work. It enabled when all the fields are filled, but enables again when I remove the text in one of them. What is wrong with this?

<form action='' method='post'>
    <input type='text' class='req' id='required_0' onkeydown='enableSubmit()' required>
    <input type='text' class='req' id='required_1' onkeydown='enableSubmit()' required>
    <input type='text' class='req' id='required_2' onkeydown='enableSubmit()' required>
    <input type='submit' value='Submit' disabled>
</form>

<script>
    function enableSubmit(){
        let inputs = document.getElementsByClassName('req');
        let btn = document.querySelector('input[type="submit"]');

        let disabled = false;
        for (var i = 0; i < inputs.length; i++){
            let changedInput = document.querySelector('#required_' + i);
            if (changedInput.value.trim() == "" || changedInput.value == null){
                btn.disabled = true;
                console.log("Button disabled");
            } else {
                btn.disabled = false;
                console.log("Button enabled")
            }
        }
    }
</script>

EDIT: Thank you for all the answers, I didn't think I would get that many - so I don't really know who I should choose as "answer" for the cred. Please comment below with your pick (and why) to help me choose.

You cannot fix this with a onkeydown, cause it will not correctly trigger the event. onkeyup does the job. Look to a working variant.

I've a bit optimised your code.

  • You already filtered out the inputs with let inputs = document.getElementsByClassName('req');
  • on first empty field we break the loop with break;

 function enableSubmit(){ let inputs = document.getElementsByClassName('req'); let btn = document.querySelector('input[type="submit"]'); let isValid = true; for (var i = 0; i < inputs.length; i++){ let changedInput = inputs[i]; if (changedInput.value.trim() === "" || changedInput.value === null){ isValid = false; break; } } btn.disabled =;isValid; }
 <form action='' method='post'> <input type='text' class='req' id='required_0' onkeyup='enableSubmit()' required> <input type='text' class='req' id='required_1' onkeyup='enableSubmit()' required> <input type='text' class='req' id='required_2' onkeyup='enableSubmit()' required> <input type='submit' value='Submit' disabled> </form>

Good answers @Max Kaps 4bis.nl. What I can add is that the code would not response on mouse events. I can cut or insert with a mouse.

My updated version

 function enableSubmit(){ let inputs = document.getElementsByClassName('req'); let btn = document.querySelector('input[type="submit"]'); let isValid = true; for (var i = 0; i < inputs.length; i++){ let changedInput = inputs[i]; if (changedInput.value.trim() === "" || changedInput.value === null){ isValid = false; break; } } btn.disabled =;isValid; }
 <form action='' method='post'> <input type='text' class='req' id='required_0' onkeyup='enableSubmit()' onmousedown='enableSubmit()' oninput='enableSubmit()' required> <input type='text' class='req' id='required_1' onkeyup='enableSubmit()' onmousedown='enableSubmit()' oninput='enableSubmit()' required> <input type='text' class='req' id='required_2' onkeyup='enableSubmit()' onmousedown='enableSubmit()' oninput='enableSubmit()' required> <input type='submit' value='Submit' disabled> </form>

In your loop, you are enabling the button as soon as you find one input which isn't null or empty. You need to change your code to check that all fields are completed.

You could do this several ways. But easiest would be to invert your logic. Set the button to be enabled. Then only disable it if any field is incomplete.

function enableSubmit(){
       let inputs = document.getElementsByClassName('req');
       let btn = document.querySelector('input[type="submit"]');

       btn.disabled = false;
       for (var i = 0; i < inputs.length; i++){
         let changedInput = document.querySelector('#required_' + i);
         if (changedInput.value.trim() == "" || changedInput.value == null){
           btn.disabled = true;
           console.log("Found an incomplete field, set disabled to true");
         }
       }

}

This might seem a bit ugly, because you are setting the button state twice. So another common approach is to use a flag instead.

function enableSubmit(){
           let inputs = document.getElementsByClassName('req');
           let btn = document.querySelector('input[type="submit"]');

           let disabled = false;
           for (var i = 0; i < inputs.length; i++){
             let changedInput = document.querySelector('#required_' + i);
             if (changedInput.value.trim() == "" || changedInput.value == null){
               disabled = true;
               console.log("Found an incomplete field, set disabled to true");
             }
           }
btn.disabled = disabled;

}

However, this will still not work perfectly, because you are calling the check on key down. When the key is pressed, the value of the field is not yet updated, and so the first time you type in the final input, the button will still be disabled. Better to use on key up. I've updated this in the fiddler below.

Fiddler link here - https://jsfiddle.net/8yaenwx7/

My input - while we are checking let's disable the button until we are sure about.

 function enableSubmit(){ let inputs = document.getElementsByClassName('req'); let btn = document.querySelector('input[type="submit"]'); let isValid = true; btn.disabled = true; for (var i = 0; i < inputs.length; i++){ let changedInput = inputs[i]; if (changedInput.value.trim() === "" || changedInput.value === null){ isValid = false; break; } } btn.disabled =;isValid; }
 <form action='' method='post'> <input type='text' class='req' id='required_0' onkeyup='enableSubmit()' onmousedown='enableSubmit()' oninput='enableSubmit()' required> <input type='text' class='req' id='required_1' onkeyup='enableSubmit()' onmousedown='enableSubmit()' oninput='enableSubmit()' required> <input type='text' class='req' id='required_2' onkeyup='enableSubmit()' onmousedown='enableSubmit()' oninput='enableSubmit()' required> <input type='submit' value='Submit' disabled> </form>

This should fix your problem:

 function enableSubmit(){ let inputs = document.getElementsByClassName('req'); let btn = document.querySelector('input[type="submit"]'); let isValid = true; for (var i = 0; i < inputs.length; i++){ let changedInput = document.querySelector('#required_' + i); if (changedInput.value.trim() === "" || changedInput.value === null){ isValid = false; } } btn.disabled =;isValid; }
 <form action='' method='post'> <input type='text' class='req' id='required_0' onkeydown='enableSubmit()' required> <input type='text' class='req' id='required_1' onkeydown='enableSubmit()' required> <input type='text' class='req' id='required_2' onkeydown='enableSubmit()' required> <input type='submit' value='Submit' disabled> </form>

In the above approach there is a loophole. Because as you loop from first field to last and even if I find only the last field filled it will enable the button. I modified the script and got it working.

function enable(){
            let  inputs = document.getElementsByClassName('req');
            let btn = document.querySelector('input[type="submit"]');
            let i;
            for(i = 0;i < inputs.length;i++){
                let change = document.querySelector('#required_'+i);
                if(change.value.trim() == "" || change.value == null){
                    break;
                }
            }
            if(i == inputs.length)
                btn.disabled = false;
        }

I have just modified the loop by breaking if the input is null or empty.

Here is a non-javascript solution with pure CSS. Less code to handle.

I added a onsubmit false on the form just as an example, just as I added input:invalid as a style. I also added some default text to show case the validation.

The pattern is validated through regex:
.* means any number of characters, including no characters.
\S is catching non-whitespaces

 form:invalid > input[type="submit"] { opacity: 0.5; pointer-events: none; } input:invalid { background-color: red; }
 <form onsubmit='return false' action='' method='post'> <input type='text' required pattern=".*\S.*" value="text"><br/> <input type='text' required pattern=".*\S.*" value=" text text "><br/> <input type='text' required pattern=".*\S.*"><br/> <input type='submit' value='Submit'> </form>

You could remove form:invalid > input[type="submit"] { and let the browser handle any errors. It wont submit unless all the requirements are fulfilled for all inputs.

 input:invalid { background-color: red; }
 <form onsubmit='return false' action='' method='post'> <input type='text' required pattern=".*\S.*" value="text"><br/> <input type='text' required pattern=".*\S.*" value=" text text "><br/> <input type='text' required pattern=".*\S.*"><br/> <input type='submit' value='Submit'> </form>

First, let's tweak your HTML a bit. Most importantly, novalidate will prevent native constraint validation from blocking form submission unless all fields are filled (because they are required . Also, don't forget to name your fields, especially for direct HTTP submission.

<form name='myForm' novalidate action='' method='post'>
  <input name='field0' required>
  <input name='field1' required>
  <input name='field2' required>
  <input type='submit' value='Submit' disabled>
</form>

Now for the JavaScript, we can actually use native validation to count how many fields are valid. We want less than 3 and, I assume, at least one?

const myForm = document.forms.myForm
// this is more efficient than adding a listener on each field separately
myForm.addEventListener('input', enableSubmit)

function enableSubmit() {
  const button = myForm[3]
  // get all the fields in an array
  const validInputCount = [...myForm.elements].slice(0, 3)
  // then count how many are valid
    .reduce((sum, input) => sum + input.checkValidity(), 0)
  // finally apply your custom rule
  button.disabled = validInputCount > 0 && validInputCount < 3
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM