-1

I currently have a dropdown that is written completely with html and css, and I currently have the functionality that: if a user clicks an option from the menu - it will open a submenu via a hidden radiobutton. However, with radiobuttons - once you select one option - you can not deselect it as the user. That is why I would like to implement the functionality of clicking a checked radiobutton deselects it (if it is in the dropdown).


 const DROPDOWN_SELECTION = document.querySelectorAll(".menu input[type='radio']");
DROPDOWN_SELECTION.forEach( element => {
    element.addEventListener("click", () => {
        if(element.checked === true){
            element.checked = false;
        }
    });
}); 
.dropdown{
    width: 250px;
    background-color:black;
    color:white;
}

.dropdown label{
    font-size:30px;
}

.dropdown ul{
    display: none;
}

[id^=btn]:checked + ul{
    display:block;
}


.dropdown input{
    display: none;
}
    <div class ="dropdown">
        <label for = "btn-Main" class="button">Dropdown List</label>
        <input type="checkbox" id="btn-Main">
        <ul class="menu">
            <li>
                <label for = "btn-Two" class="first">Option A</label>
                <input type="radio" name="faction" id="btn-Two">
                <ul>
                    <li>Option A.1</li>
                    <li>Option A.2</li>
                </ul>
            </li>

            <li>
                <label for = "btn-Three" class="second">Option B
                    <span class ="arrow down"></span>
                </label>
                <input type="radio" name="faction" id="btn-Three">
                <ul>
                    <li>Option B.1</li>
                    <li>Option B.2</li>
                </ul>
            </li>

        </ul>
    </div>

The above code was my attempt at creating this functionality, however upon testing - the submenus no longer open. My hypothesis is that the code checks if the radio button is checked after the checked value has changed from the user input, and not before. Thus, a user cannot open the submenu as it will automatically uncheck. I have added just the tiniest bit of styling so that the end result makes more sense visually


The reason I did not use checkboxes instead of radio buttons is because of the functionality that you can only select one option at a time as a radio button. This means only one submenu may be open at any given time and will avoid clutter and automatically close other submenus. I would like the option to further reduce clutter by allowing users to close a submenu that they are viewing by clicking on it again.

There are some people who have had similar issues. However, their code was in jQuery, whilst mine is in javascript - and I would like to find a solution that is in javascript as I am new to web design and would prefer not to learn a new language before I finish my first project. Regardless, here are some links from people who had similar issues (in jQuery):


Stack Overflow JQuery version of this question:
Uncheck Radio Button with double click
how to uncheck a radio button

yjzhou
  • 67
  • 1
  • 8
  • Please provide your HTML, preferably in a working example that demonstrates your issue. – Marc Mar 08 '23 at 17:14
  • The second question you linked has an answer for plain JS (the most up voted and accepted one) – cloned Mar 08 '23 at 17:15
  • 1
    Does this answer your question? [How to uncheck a radio button?](https://stackoverflow.com/questions/2117538/how-to-uncheck-a-radio-button) – cloned Mar 08 '23 at 17:16
  • 1
    @cloned Isn't their code doing exactly what the answer there says? – Barmar Mar 08 '23 at 17:17
  • @cloned that is the issue, my proposed code seems to do similar to what is suggested, however it does not seem to work. However, if you give me a moment I will also upload my html in a sample. If you look at my js code though you can see I have the element.checked = false; statement – yjzhou Mar 08 '23 at 17:19
  • 1
    Your problem isn't with unchecking the radio box, it's with opening the submenu. But you haven't shown the code that does this, so we can't see why this additional code is interfering with it. Please post a [mre]. – Barmar Mar 08 '23 at 17:20
  • @Barmar thank you for this. Give me a few moments and I will try to produce a minimal reproducible example. – yjzhou Mar 08 '23 at 17:21
  • Maybe a checkbox would be more appropriate if you need to toggle the state. In any case, adapt your example (and maybe title?) So we can better see what's going on. – cloned Mar 08 '23 at 17:25
  • I have updated my question with what I hope is a more suitable title alongside a code snippet. I have embellished the styling just the tiniest amount w a black background and a different font size for menus - just so that the visuals make more sense – yjzhou Mar 08 '23 at 17:46
  • I'm confused, when you remove your JavaScript the only issue I see is that last submenu that was open remains open when you close and open the menu again. Are you just trying to hide them when the parent menu is closed? – Adam H Mar 08 '23 at 17:55
  • @cloned - so the reason I didn't use a checkbox was because radio buttons automatically toggle other radio buttons checked value to false. However, I guess perhaps it might be easier to use javascript to toggle every other checkbox to false instead of changing how radio buttons fundamentally work? – yjzhou Mar 08 '23 at 17:55
  • @AdamH I'm trying to hide the submenus if they get clicked again. so I want the user to be able to close submenus. Reasoning for this is that the code snippet is just the minimum reproducible example, and the real dropdown is much larger - thus allowing the user to close the currently open submenu would help to decrease clutter and more easily navigate the initial dropdown – yjzhou Mar 08 '23 at 17:59
  • 1
    So you want to enforce only displaying one submenu at a time? – Adam H Mar 08 '23 at 18:00
  • @AdamH that is part of it (hence the radio button) - but I would also like the user to be able to close the submenu that they are on as well. – yjzhou Mar 08 '23 at 18:01

2 Answers2

3

Here is a solution that uses checkboxes and then just unchecks other checkboxes when a sub menu is clicked. Same functionality as the radio buttons but uses checkboxes so the users can easily close a submenu.

(function() {
  // get all the checkboxes (submenus)
  const menuHeaders = document.querySelectorAll('div.dropdown > .menu input[type="checkbox"]');
  // loop over them
  [...menuHeaders].forEach((mnu) => {
    // add a click event handler
    mnu.addEventListener('click', (e) => {
      // loop over all submenu headers
        [...menuHeaders].forEach(function(item) {
        // check if the header is the clicked header
        if (item !== e.target){
          // uncheck this option
            item.checked = false;
        }
      });
    })
  })
})()
.dropdown{
    width: 250px;
    background-color:black;
    color:white;
}

.dropdown label{
    font-size:30px;
}

.dropdown ul{
    display: none;
}

[id^=btn]:checked + ul{
    display:block;
}


.dropdown input{
    display: none;
}
<div class="dropdown">
  <label for="btn-Main" class="button">Dropdown List</label>
  <input type="checkbox" id="btn-Main">
  <ul class="menu">
    <li>
      <label for="btn-Two" class="first">Option A</label>
      <input type="checkbox" name="faction" id="btn-Two">
      <ul>
        <li>Option A.1</li>
        <li>Option A.2</li>
      </ul>
    </li>

    <li>
      <label for="btn-Three" class="second">Option B
        <span class="arrow down"></span>
      </label>
      <input type="checkbox" name="faction" id="btn-Three">
      <ul>
        <li>Option B.1</li>
        <li>Option B.2</li>
      </ul>
    </li>

    <li>
      <label for="btn-Four" class="second">Option C
        <span class="arrow down"></span>
      </label>
      <input type="checkbox" name="faction" id="btn-Four">
      <ul>
        <li>Option C.1</li>
        <li>Option C.2</li>
      </ul>
    </li>
  </ul>
</div>
Adam H
  • 1,750
  • 1
  • 9
  • 24
0

So I have found a way to implement the functionality I am talking about, however - it does add an extra step for the user if they want to open another submenu as they are forced to close the current submenu first. I will try to find a solution to fix this but for now here is the current solution - simply change the js file:

var subMenuOpen = false;

const DROPDOWN_SELECTION = document.querySelectorAll(".menu input[type='radio']");
 DROPDOWN_SELECTION.forEach( element => {
    element.addEventListener("click", () => {
        if(subMenuOpen === true){
            element.checked = false;
            subMenuOpen = false;
        }
        else {
            subMenuOpen = true;
        }
    });
 }); 
yjzhou
  • 67
  • 1
  • 8