skip to Main Content

I’m trying to streamline my code and running into a brick wall. In the actual project, I have ten radio inputs that appear on a button click. What I want is that when a radio option is selected, all radios disappear and the checked option becomes the background image.

This has allowed me to do that:

optionOne.addEventListener("click", function() {
  showButton.style.backgroundImage = `url("${optionOneImage}")`;
  showButton.innerHTML = "";
  
  optionsGrid.style.display = "none";
  for (let i = 0; i < optionRadios.length; i++) {
    optionRadios[i].classList.replace("active", "hide");
   }
});

However, since there are 10 options, is there some type of switch statement that I could write that would read what was clicked and collapse the radio options? I have to implement something similar for something with over 40 radio options, so I want to make this as concise as possible.

Here’s a CodePen for the full working code as I have it.

const showButton = document.getElementById("option-button");
const optionsGrid = document.getElementById("option-grid");
const optionRadios = document.getElementsByClassName("option-radio");
const optionOne = document.getElementById("1");
const optionTwo = document.getElementById("2");
const optionThree = document.getElementById("3");
const optionFour = document.getElementById("4");
const optionOneImage = document.getElementById("option-1-image").src;
const optionTwoImage = document.getElementById("option-2-image").src;
const optionThreeImage = document.getElementById("option-3-image").src;
const optionFourImage = document.getElementById("option-4-image").src;

showButton.addEventListener("click", showOptions);

function showOptions() {
  let array = [];

  for (let i = 0; i < optionRadios.length; i++) {
    array.push(optionRadios[i].classList.value);
  }

  if (array.includes("option-radio hide")) {
    optionsGrid.style.animation = "open-animation 100ms linear 1";
    optionsGrid.style.display = "grid";
    for (let i = 0; i < optionRadios.length; i++) {
      optionRadios[i].classList.replace("hide", "active");
    }
  } else {
    optionsGrid.style.display = "none";
    for (let i = 0; i < optionRadios.length; i++) {
      optionRadios[i].classList.replace("active", "hide");
    }
  }
}

optionOne.addEventListener("click", function() {
  showButton.style.backgroundImage = `url("${optionOneImage}")`;
  showButton.innerHTML = "";

  optionsGrid.style.display = "none";
  for (let i = 0; i < optionRadios.length; i++) {
    optionRadios[i].classList.replace("active", "hide");
  }
});

optionTwo.addEventListener("click", function() {
  showButton.style.backgroundImage = `url("${optionTwoImage}")`;
  showButton.innerHTML = "";

  optionsGrid.style.display = "none";
  for (let i = 0; i < optionRadios.length; i++) {
    optionRadios[i].classList.replace("active", "hide");
  }
});

optionThree.addEventListener("click", function() {
  showButton.style.backgroundImage = `url("${optionThreeImage}")`;
  showButton.innerHTML = "";

  optionsGrid.style.display = "none";
  for (let i = 0; i < optionRadios.length; i++) {
    optionRadios[i].classList.replace("active", "hide");
  }
});

optionFour.addEventListener("click", function() {
  showButton.style.backgroundImage = `url("${optionFourImage}")`;
  showButton.innerHTML = "";

  optionsGrid.style.display = "none";
  for (let i = 0; i < optionRadios.length; i++) {
    optionRadios[i].classList.replace("active", "hide");
  }
});
.hide {
  display: none;
}

.active {
  display: block;
}

#option-button {
  width: 600px;
  height: 200px;
}

#option-grid {
  display: none;
  grid-template-columns: repeat(2, 1fr);
  width: 1250px;
  height: 450px;
  background-color: lightblue;
  box-shadow: 0px 5px 5px rgba(0, 0, 0, .3);
  place-items: center;
  overflow: hidden;
}

@keyframes open-animation {
  0% {
    opacity: 0;
    transform: translateY(-5px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}
<fieldset id="console-select">
  <legend>Radio Option</legend>
  <button type="button" id="option-button">Select</button>
  <div id="option-grid">
    <div class="option-radio hide">
      <label for="1">
        <input type="radio" name="option" value="1" id="1" hidden>
        <img src="https://placehold.co/600x200" id="option-1-image">
      </label>
    </div>
    <div class="option-radio hide">
      <label for="2">
        <input type="radio" name="option" value="2" id="2" hidden>
        <img src="https://placehold.co/600x199" id="option-2-image">
      </label>
    </div>
    <div class="option-radio hide">
      <label for="3">
        <input type="radio" name="option" value="3" id="3" hidden>
        <img src="https://placehold.co/600x198" id="option-3-image">
      </label>
    </div>
    <div class="option-radio hide">
      <label for="4">
        <input type="radio" name="option" value="4" id="4" hidden>
        <img src="https://placehold.co/600x197" id="option-4-image">
      </label>
    </div>
  </div>
</fieldset>

4

Answers


  1. You can add a class to all the radios (or also query only radio elements) and then do a loop to add the event listener to all the elements.

    For example:

    <form>
      <input type="radio" name="option" value="1" id="1" hidden>
      <input type="radio" name="option" value="2" id="2" hidden>
      <input type="radio" name="option" value="3" id="3" hidden>
    </form>
    
    const allRadios = document.querySelectorAll("form input[type='radio']") //gets all input type radio inside form
    allRadios.forEach((singleRadioElement)=>{ // loops over all the elements
      singleRadioElement.addEventListener("click", ()=>{ // adds the event listener for each element
        showButton.style.backgroundImage = `url("${optionOneImage}")`;
        showButton.innerHTML = "";
      
        optionsGrid.style.display = "none";
        for (let i = 0; i < optionRadios.length; i++) {
          optionRadios[i].classList.replace("active", "hide");
        }
      })
    })
    
    Login or Signup to reply.
  2. You can address elements/json objects dynamically in JS like this:

    for(let i = 1; i < numOptions; i++) {
      var currVariable = eval("option" + i);
      currVariable.addEventListener("click", ...
    }

    It’s much easier if you use this notation "option1", "option2" instead of "one", "two", "three".

    Login or Signup to reply.
  3. You can add the eventListener to the form instead of to each individual radio button. Then listen for the change event to know a radio button was selected.

    You can use the event object to know which radio button was selected.

    If you want you can still use a for loop to hide each button individually, or you could hide the whole form.

    let form = document.querySelector("form")
    let btns = document.querySelector("input[name=selectback]")
    
    
    form.addEventListener("change", (event) => {
        console.log("you clicked on: " + event.target.value)
      
        for(let btn of btns){
          btn.classList.replace("active", "hide")
        }
    })
    <form>
    
    <input type="radio" id="back1" name="selectback" value="back1">
    <label for="back1">background 1</label><br>
    <input type="radio" id="back2" name="selectback" value="back2">
    <label for="back2">background 2</label><br>
    <input type="radio" id="back3" name="selectback" value="back3">
    <label for="back3">background 3</label><br>
    
    </form>
    Login or Signup to reply.
  4. Event bubbling is what you’re looking for

    const urlToIdMap = {
      1: "https://placehold.co/600x200",
      2: "https://placehold.co/600x199",
      3: "https://placehold.co/600x198",
      4: "https://placehold.co/600x197"
    };
    
    optionsGrid.addEventListener("click", (event) => {
      const idBubbledUp = event.target.id;
      switch (idBubbledUp) {
        case "1": {
          showButton.style.backgroundImage = `url("${urlToIdMap[idBubbledUp]}")`;
          break;
        }
        case "2": {
          showButton.style.backgroundImage = `url("${urlToIdMap[idBubbledUp]}")`;
          break;
        }
        case "3": {
          showButton.style.backgroundImage = `url("${urlToIdMap[idBubbledUp]}")`;
          break;
        }
        case "4": {
          showButton.style.backgroundImage = `url("${urlToIdMap[idBubbledUp]}")`;
          break;
        }
      }
      hideRadioGrid();
    });
    
    function hideRadioGrid() {
      showButton.innerHTML = "";
      optionsGrid.style.display = "none";
      for (let i = 0; i < optionRadios.length; i++) {
        optionRadios[i].classList.replace("active", "hide");
      }
    }
    

    CodePen

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search