js
const navItems = document.querySelectorAll('.navbar__items')
const dropDown = document.querySelectorAll('.dropdown')
dropDown.forEach(element => {
element.addEventListener('click',()=>{
{
navItems.forEach(nav =>{
nav.classList.toggle('drop')
})
}
})
})
HTML
<ul class="navbar">
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
</ul>
CSS
.navbar{
position: relative;
}
.navbar__items{
position: absolute;
display: none;
}
.drop{
display: block;
}
I have a navbar and each of these navbar items have dropdown items. I want to show these dropdown items when I click on the 'dropdown' class. But the problem is when I click on one of them all the dropdowns are visible. How do I show only the list I've clicked on?
js
const navItems = document.querySelectorAll('.navbar__items')
const dropDown = document.querySelectorAll('.dropdown')
dropDown.forEach(element => {
element.addEventListener('click',()=>{
{
navItems.forEach(nav =>{
nav.classList.toggle('drop')
})
}
})
})
HTML
<ul class="navbar">
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
</ul>
CSS
.navbar{
position: relative;
}
.navbar__items{
position: absolute;
display: none;
}
.drop{
display: block;
}
I have a navbar and each of these navbar items have dropdown items. I want to show these dropdown items when I click on the 'dropdown' class. But the problem is when I click on one of them all the dropdowns are visible. How do I show only the list I've clicked on?
Share Improve this question edited Aug 26, 2021 at 4:59 Aanshumaan Shrijai 1191 gold badge1 silver badge11 bronze badges asked Aug 26, 2021 at 4:24 Gaurav TamangGaurav Tamang 1192 silver badges10 bronze badges 04 Answers
Reset to default 3Enter the below code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
background-color: #3498DB;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #2980B9;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd;}
.show {display: block;}
</style>
</head>
<body>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Click</button>
<div id="myDropdown" class="dropdown-content">
<a href="#home">Clicked</a>
<a href="#about">Clicked</a>
<a href="#contact">Clicked</a>
</div>
</div>
<script>
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
</body>
</html>
As mentioned in ments it is better to use Event Delegation technique.
The algorithm is quite simple:
- Add listener on the parent element
- On click check if dropdown-opener was clicked
- Get drop-down which I need to open
- Close other dropdowns
- Open dropdown from 3.
const allDropdowns = document.querySelectorAll('.navbar__items')
const DROP_CLASS = 'drop';
const navbar = document.querySelector('.navbar');
navbar.addEventListener('click', ({target}) => {
if (!target.classList.contains('dropdown')) return;
const parent = target.parentNode;
const navItems = parent
.querySelector('.navbar__items');
allDropdowns.forEach(el => el !== navItems && el.classList.remove(DROP_CLASS));
if (navItems) {
navItems.classList.toggle(DROP_CLASS);
}
});
.navbar{
position: relative;
}
.navbar__items{
position: absolute;
left: 80px;
display: none;
}
.drop{
display: block;
}
<ul class="navbar">
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
</ul>
Use the event target to get the parentNode, then use the parentNode to query the hidden element as all your elements are grouped in the same parent/child grouping. Also you can set an initial class for hidden, display: none;
in each element and add it on click. A forEach loop sets each elements display to none using the hidden class on click.
const navItems = document.querySelectorAll('.navbar__items')
const dropDown = document.querySelectorAll('.dropdown')
// callback function that passes in the event => e from your listener
function showDropdown (e){
// set each navbar__items element display: none using hidden class
navItems.forEach(el => el.classList.add('hidden'))
// query the specific .navbar__items in the event.targets group
let dd = e.target.parentNode.querySelector('.navbar__items')
// remove the hidden class a nd show the dropdown for this event.target
dd.classList.remove('hidden')
}
// iterate over the dropdown element
dropDown.forEach(element => {
// function showDropdown on click
element.addEventListener('click', showDropdown)
})
.navbar {
position: relative;
}
.navbar__items {
position: absolute;
left: 75px;
}
.hidden {
display: none;
}
<ul class="navbar">
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items hidden">
<li><a href="#">clicked 1</a></li>
<li><a href="#">clicked 1</a></li>
<li><a href="#">clicked 1</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items hidden">
<li><a href="#">clicked 2</a></li>
<li><a href="#">clicked 2</a></li>
<li><a href="#">clicked 2</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown">click</div>
<ul class="navbar__items hidden">
<li><a href="#">clicked 3</a></li>
<li><a href="#">clicked 3</a></li>
<li><a href="#">clicked 3</a></li>
</ul>
</li>
</ul>
Rather than using addEventlistener you should add onclick method in html to every drop-down with same method name but change the ul class name with for each drop-down and then pass class name in method and then toggle the drop-down with parameter class name.
For example,
function onClick(item) {
if (document.getElementsByClassName(item).classList.contains('hidden')) {
document.getElementsByClassName('dropdown').classList.remove('hidden');
}
if (!document.getElementsByClassName(item)[0].classList.contains('hidden')) {
document.getElementsByClassName('dropdown').classList.add('hidden');
}
}
<ul class="navbar">
<li class="nav-menu">
<div class="dropdown" onclick="onClick('navbar_items1')">click</div>
<ul class="navbar__items1 hidden">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown" onclick="onClick('navbar_items2')">click</div>
<ul class="navbar__items2 hidden">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
<li class="nav-menu">
<div class="dropdown" onclick="onClick('navbar_items3')">click</div>
<ul class="navbar__items3 hidden">
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
<li><a href="#">clicked</a></li>
</ul>
</li>
</ul>