So I have a side navigation that has a sub-menu in some of the list, and I'm trying to display the sub-menu only when it's clicked.
Here is the HTML
<div class="sidebar">
<ul class="nav">
<li class="main-menu" onclick="dispDrop()"><a href="">Item 1</a>
<ul class="sub-menu">
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
</ul>
</li>
<li><a href="">Item 2</a></li>
<li><a href="">Item 3</a></li>
<li class="main-menu" onclick="dispDrop()"><a href="">Item 4</a>
<ul class="sub-menu">
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
</ul>
</li>
<li><a href="">Item 5</a></li>
<li><a href="">Item 6</a></li>
</ul>
</div>
Here is its CSS
.nav ul {
display: none;
position: relative;
padding: 0px;
}
.nav li.active ul {
display: block;
}
Here is the javascript
<script type="text/javascript">
const navItem = document.querySelector('.main-menu');
function dispDrop() {
navItem.classList.toggle("active");
}
</script>
At first it was working fine, but when I added a submenu to another list, it started glitching and won't display the submenu.
Is there a way to target only the clicked <li> and only add/toggle the class to that clicked <li>?
What you can do is adding this to onclick="dispDrop()"
And then do the following.
function dispDrop(obj) {
obj.classList.toggle("active");
}
Demo
function dispDrop(obj) {
obj.classList.toggle("active");
}
.nav ul {
display: none;
position: relative;
padding: 0px;
}
.nav li.active ul {
display: block;
}
<div class="sidebar">
<ul class="nav">
<li class="main-menu" onclick="dispDrop(this)"><a href="#">Item 1</a>
<ul class="sub-menu">
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
</ul>
</li>
<li><a href="">Item 2</a></li>
<li><a href="">Item 3</a></li>
<li class="main-menu" onclick="dispDrop(this)"><a href="#">Item 4</a>
<ul class="sub-menu">
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
</ul>
</li>
<li><a href="">Item 5</a></li>
<li><a href="">Item 6</a></li>
</ul>
</div>
Some issues that I have Identified are listed below.
navItem as document.querySelector('.main-menu'). This will always returns the first DOM element with that class name. Not your required target.I have fixed that by toggling the class list of the target elemet from the click tiggered. This will give the required target where the click is triggered.
Call e.preventDefault(); e.stopPropagation(); inside the click event to stop the click event triggering the anchor tag click event.
Working Fiddle
function dispDrop(e) {
e.currentTarget.classList.toggle("active");
e.preventDefault();
e.stopPropagation();
}
.nav ul {
display: none;
position: relative;
padding: 0px;
}
.nav li.active ul {
display: block;
}
<div class="sidebar">
<ul class="nav">
<li class="main-menu" onclick="dispDrop(event)">
<a href="">Item 1</a>
<ul class="sub-menu">
<li><a href="">Sub-item 11</a></li>
<li><a href="">Sub-item 11</a></li>
<li><a href="">Sub-item 11</a></li>
<li><a href="">Sub-item 11</a></li>
</ul>
</li>
<li><a href="">Item 2</a></li>
<li><a href="">Item 3</a></li>
<li class="main-menu" onclick="dispDrop(event)">
<a href="">Item 4</a>
<ul class="sub-menu">
<li><a href="">Sub-item 12</a></li>
<li><a href="">Sub-item 12</a></li>
<li><a href="">Sub-item 12</a></li>
<li><a href="">Sub-item 12</a></li>
</ul>
</li>
<li><a href="">Item 5</a></li>
<li><a href="">Item 6</a></li>
</ul>
</div>
I rewrite a little bit your code. The problem occurs from the anchor. You can
remove the anchor an style the li tag to have the anchor feeling (cursor: pointer; etc) or
you add a # to your href. that will avoid to follow the link
Then I pass with your onclick event the currecnt clickent object. Then you eventHandler knows which element was clicked.
function dispDrop(event) {
event.querySelector('ul').classList.toggle("hide");
}
.nav ul {
position: relative;
padding: 0px;
}
.hide {
display: none;
position: relative;
}
<div class="sidebar">
<ul class="nav">
<li class="main-menu" onclick="dispDrop(this)">
<a href="#">Item 1</a>
<ul class="sub-menu hide">
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
<li><a href="">Sub-item 1</a></li>
</ul>
</li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li class="main-menu clicki" onclick="dispDrop(this)">
<a href="#">Item 4</a>
<ul class="sub-menu hide">
<li><a href="#">Sub-item A </a></li>
<li><a href="#">Sub-item 1</a></li>
<li><a href="#">Sub-item 1</a></li>
<li><a href="#">Sub-item 1</a></li>
</ul>
</li>
<li><a href="#">Item 5</a></li>
<li><a href="#">Item 6</a></li>
</ul>
</div>