0

How do you check if a set of elements (7 total), that all have the same class name, all have the display property set to none, using Javascript? If all those display properties are set to none then set the button disable = false. If any of those elements, even just one, have display equal to block, set the button disable = true. Below is the failing attempt:

const errorMessages = document.querySelectorAll(".invalid-password")
const submitButton = document.querySelector("#account_submit")
submitButton.addEventListener("click", () => {
    errorMessages.forEach(message => {
        if (message.style.display !== "none") {
            submitButton.disabled = true;
        } else {
            submitButton.disabled = false;
        }
    })
})
ckingchris
  • 559
  • 1
  • 12
  • 25

4 Answers4

2

You need to break from the loop if one of the elements is appearing. However, there is no built-in function to break from the foreach loop in JavaScript, so, you can use this method in this post:

const errorMessages = document.querySelectorAll(".invalid-password")
const submitButton = document.querySelector("#account_submit")

try {

submitButton.addEventListener("click", () => {
    errorMessages.forEach(message => {
        console.log(message.style.display)
        if (message.style.display !== "none") {
            submitButton.disabled = true;
            throw BreakException;
        } else {
            submitButton.disabled = false;
        }
    })
})

} catch(e) { if (e !== BreakException) throw e; }
<button id="account_submit">Click</button>

<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:block">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>

A better way would be to define a function to check this condition and use it on click:

const errorMessages = document.querySelectorAll(".invalid-password")
const submitButton = document.querySelector("#account_submit")

submitButton.addEventListener("click", () => {
    submitButton.disabled = checkVisibility();
})

function checkVisibility(){
  for(let i = 0; i < errorMessages.length; i++){
        if (errorMessages[i].style.display !== "none") {
            return true;
        }
   }
   return false;
}
<button id="account_submit">Click</button>

<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:block">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
<h6 class="invalid-password" style="display:none">test</h6>
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
2

Since ECMAScript 2015 (ES 6) you could use Array.from and Array.some:

const disableButton =  Array.from(errorMessages).some(({style}) => style.display !== "none"));
submitButton.disabled = disableButton;
dpdenton
  • 300
  • 1
  • 9
1

Unless you use inline style to hide divs, their style.display property will be empty, so the best bet is to test if any of them has style.display == 'block' to disable submit button and it's not a good idea to do these checks inside button click event, because it could be disabled and you won't have a chance to enable it again.

Show or hide your divs when you validate the forms and do the checks to enable or disable the submit button:

const errorMessages = document.querySelectorAll(".invalid-password");
const submitButton = document.querySelector("#account_submit");
const field1 = document.querySelector("#field1");
function checkMessages() {
    submitButton.disabled = false;
    errorMessages.forEach(message => {
        if(message.style.display == 'block') {
            submitButton.disabled = true;
            return;
        }
    });
}
field1.addEventListener("input", function() {
    if(this.value == '') {
        errorMessages[0].style.display = 'block';
    } else {
        errorMessages[0].style.display = 'none';
    }
    checkMessages();
});
submitButton.addEventListener("click", () => {
    event.preventDefault();
    console.log('Enabled');
})
.invalid-password {
    display:none;
}
<input id="field1" type="text" value="">
<div class="invalid-password">1</div>
<div class="invalid-password">2</div>
<div class="invalid-password">3</div>
<div class="invalid-password">4</div>
<div class="invalid-password">5</div>
<div class="invalid-password">6</div>
<input type="submit" id="account_submit" value="Submit" disabled="true">
Triby
  • 1,739
  • 1
  • 16
  • 18
0

Might not be the most efficient method but another way to approach this is to define a variable equal to 0 and for each message, if the display is none increment the variable by 1. Then check if the variable = 7 (which means all 7 elements were display: none) to toggle the disabled.

const errorMessages = document.querySelectorAll(".invalid-password");
const submitButton = document.querySelector("#account_submit");

submitButton.addEventListener("click", () => {
    let disabled = 0;
    errorMessages.forEach(message => {
        if (message.style.display !== "none") {
           disabled++;
        }
        
        if (disabled === 7) {
          submitButton.disabled = true;
        } else {
          submitButton.disabled = false;
        }
    })
  console.log(disabled);
})
.invalid-password {
  display: none;
 }
<button id="account_submit">Submit</button>

<p class="invalid-password">Invalid password1</p>
<p class="invalid-password">Invalid password2</p>
<p class="invalid-password">Invalid password3</p>
<p class="invalid-password">Invalid password4</p>
<p class="invalid-password">Invalid password5</p>
<p class="invalid-password">Invalid password6</p>
<p class="invalid-password">Invalid password7</p>
Xenvi
  • 887
  • 5
  • 10