Home > Back-end >  How can I hide a button until at least three input checkboxes (one from each separate set of six) ar
How can I hide a button until at least three input checkboxes (one from each separate set of six) ar

Time:10-15

I have three lists (HTML Fieldset elements) with six foods (HTML input elements - starting as unchecked) in each. I would like to keep a button element below these three lists hidden until at least one food from each of the three lists has been checked. When at least one food from each list has been checked I would like the button to unhide.

This will unhide the button when one of the inputs in the first fieldset is clicked... but I need to expand the functionality so that the button will only appear when at least one of each of the 3x fieldsets (protein, carbs, and fats) is selected.

// Add variable for the DOM element button with id "generate-meals" 
let generateMealButton = document.getElementById("generate-meals");

generateMealButton.classList.add("hide");

// Add an eventlistener to generate meal button to listen for a "click" event and run the 
// function "runMealGenerator when the event occurs"
generateMealButton.addEventListener("click", runMealGenerator);

// find all input fields
const proteinInputs = document.querySelectorAll("input[class='protein-input']");
console.log(proteinInputs[0].checked)
const carbInputs = document.querySelectorAll("input[class='carb-input']");
console.log(carbInputs)
const fatInputs = document.querySelectorAll("input[class='fat-input']");
console.log(fatInputs)
// add click event-listener for all input buttons
proteinInputs.forEach((input) => {
  input.addEventListener("click", checkProteinInput);
});

// check if any input buttons are 'checked'
function checkProteinInput() {
  // if the macroChoice button is 'not' hidden, then unhide it
  console.log(proteinInputs[0].checked)
  if (generateMealButton.classList.contains("hide")) {
    generateMealButton.classList.remove("hide");
  }
}

function runMealGenerator() {
console.log("Dummy Function Added")
}
<!-- This section contains the 3x menus of sample foods the user can select for inclusion in their meal plan ideas  -->
<section id="foodListContainer">
  <!-- Small section for direction to the user - instructions on how to proceed -->
  <section class="food-groups" id="generator_instructions">
    <h3 id="food-heading">Instructions</h3>
    <p>Please select at least one food from each group for inclusion in meal plans:</p>
  </section>
  <!-- Fieldset to contain checkboxes for each Protein food option for selection by user -->
  <fieldset class="food-groups" id="proteinFieldset">
    <legend>Protein:</legend>
    <!-- Each Protein input is housed in a div to enable dematcation & styling -->
    <div>
      <label for="chicken">Chicken</label>
      <input class="protein-input" type="checkbox" id="chicken" name="chicken">
    </div>
    <div>
      <label for="turkey">Turkey</label>
      <input class="protein-input" type="checkbox" id="turkey" name="turkey">
    </div>
    <div>
      <label for="fish">Fish</label>
      <input class="protein-input" type="checkbox" id="fish" name="fish">
    </div>
    <div>
      <label for="beef">beef</label>
      <input class="protein-input" type="checkbox" id="beef" name="beef">
    </div>
    <div>
      <label for="eggs">eggs</label>
      <input class="protein-input" type="checkbox" id="eggs" name="eggs">
    </div>
    <div>
      <label for="pork">pork</label>
      <input class="protein-input" type="checkbox" id="pork" name="pork">
    </div>
  </fieldset>
  <!-- Fieldset to contain checkboxes for each Carbohydrate food option -->
  <fieldset class="food-groups">
    <legend>Carbohydrate:</legend>
    <!-- Each Carbohydrate input is housed in a div to enable dematcation & styling -->
    <div>
      <label for="bread">Bread</label>
      <input class="carb-input" type="checkbox" id="bread" name="bread">
    </div>
    <div>
      <label for="pasta">Pasta</label>
      <input class="carb-input" type="checkbox" id="pasta" name="pasta">
    </div>
    <div>
      <label for="rice">Rice</label>
      <input class="carb-input" type="checkbox" id="rice" name="rice">
    </div>
    <div>
      <label for="oats">Oats</label>
      <input class="carb-input" type="checkbox" id="oats" name="oats">
    </div>
    <div>
      <label for="cereal">Cereal</label>
      <input class="carb-input" type="checkbox" id="cereal" name="cereal">
    </div>
    <div>
      <label for="quinoa">Quinoa</label>
      <input class="carb-input" type="checkbox" id="quinoa" name="quinoa">
    </div>
  </fieldset>
  <!-- Fieldset to contain checkboxes for each Fat food option -->
  <fieldset class="food-groups">
    <legend>Fat:</legend>
    <!-- Each Fat input is housed in a div to enable dematcation & styling -->
    <div>
      <label for="butter">Butter</label>
      <input class="fat-input" type="checkbox" id="butter" name="butter">
    </div>
    <div>
      <label for="cheese">Cheese</label>
      <input class="fat-input" type="checkbox" id="cheese" name="cheese">
    </div>
    <div>
      <label for="cream">Cream</label>
      <input class="fat-input" type="checkbox" id="cream" name="cream">
    </div>
    <div>
      <label for="nuts">Nuts</label>
      <input class="fat-input" type="checkbox" id="nuts" name="nuts">
    </div>
    <div>
      <label for="bacon">Bacon</label>
      <input class="fat-input" type="checkbox" id="bacon" name="bacon">
    </div>
    <div>
      <label for="olive-oil">Olive Oil</label>
      <input class="fat-input" type="checkbox" id="olive-oil" name="olive-oil">
    </div>
  </fieldset>
  <!-- End of foodListContainer section -->
  <!-- Button to allow the user proceed to generate meal plan ideas when they have selected
            All foods they wish to include/exclude -->
  <section id="generate-container">
    <button id="generate-meals">Generate A Meal Plan</button>
  </section>
</section>

CodePudding user response:

You will need to iterate over ALL checkboxes, whether at least one of each section is checked. And you will need to do this, also, when a checkbox is unchecked, because probably you want to hide the button again, when the condition is not met anymore ...

The straight forward approach would be the following

function checkInputs() {
  let p = false, f = false, c = false; //protein, carbon, fat
  for (let i = 0; i < proteinInputs.length; i  ) {
    if (proteinInputs[i].checked) { p = true; break;} //we found at least one
  }
  for (let i = 0; i < fatInputs.length; i  ) {
    if (fatInputs[i].checked) { f = true; break;} //we found at least one
  }
  for (let i = 0; i < carbonInputs.length; i  ) {
    if (carbonInputs[i].checked) { c = true; break;} //we found at least one
  }

  if (p && f && c) {  //found at least one in each section
    //show the button
    generateMealButton.classList.remove("hide");
  } else {  //at least one is missing
    //hide the button
    generateMealButton.classList.add("hide");
  }
}

and add this checkInputs to all your checkboxes (ie not only for proteins, but also for fat and carbons)

Btw. You don't need to explicitly check with classList.contains if you are using classList.add or classList.remove. Those functions will take care of that. Ie, it won't add the same class twice if it's already contained, and there is no error if you try to remove a class, that isn't contained in the classList)

Of course you can optimize this code. For instance just evalute the checkbox that was just changed and keep a counter for each of the sections. And when all counters are > 0 unhide the button, and hide the button when one goes to zero ...

let cb = document.querySelectorAll("input[type='checkbox']")
for (let i = 0; i < cb.length; i  ) cb[i].addEventListener("change", check);

let c = 0, f= 0, p= 0
function check(event) {

  let addval = event.currentTarget.checked ? 1 : -1
  switch(event.currentTarget.getAttribute("data-tag")) {
    case "f": f  = addval; break;
    case "c": c  = addval; break;
    case "p": p  = addval; break;
  }
  
  console.log(f,c,p);
  if (f && c && p)
    document.getElementById("thebutton").classList.remove("hide")
  else
    document.getElementById("thebutton").classList.add("hide")
}
.hide {
  display: none;
}
<input type="checkbox" data-tag="f"/>fat
<input type="checkbox" data-tag="c"/>carbon
<input type="checkbox" data-tag="p"/>protein

<input type="checkbox" data-tag="f"/>fat2
<input type="checkbox" data-tag="c"/>carbon2
<input type="checkbox" data-tag="p"/>protein2


<input id="thebutton" type="button" value="create meal" class="hide">

  • Related