Reputation: 25
I would like to dynamically add an 'active' class to the navigation menu link when it is clicked using addEventListener. The nav menu is has also been added dynamically. I need to do this with only JavaScript. Thank you for any help.
Here is what I have so far. Not sure where to go from here
const navElements = document.querySelectorAll('section')
const navBar = document.getElementById('navbar__list')
navElements.forEach(function(section){
const navlistElement = `<li class='menu__link ${section.className}' data-link=${section.id}><a href="#${section.id}">${section.dataset.nav}</li>`
navBar.insertAdjacentHTML('beforeend',navlistElement)
})
const activeClasses = document.querySelectorAll('.menu__link');
for (x of activeClasses) {
x.addEventListener('click', function(event) {
event.preventDefault();
x.removeClass('active');
$(this).addClass('active');
});
}
<nav class="navbar__menu">
<!-- Navigation starts as empty UL that will be populated with JS -->
<ul id="navbar__list"></ul>
</nav>
...
<section id="section1" data-nav="Section 1" class="your-active-class">
<div class="landing__container">
<h2>Section 1</h2>
<p>Lorem ipsum dolor sit amet</p>
</div>
</section>
...
Upvotes: 1
Views: 1183
Reputation: 12929
The main reason it isn't working for you is that the elements don't exist in the document yet when you try to add the listeners.
There are two ways to fix this. One would be to add a listener to each <li>
as you create them and before inserting them into the DOM. But the simpler solution is to use event delegation and attach one listener to the <ul>
element and handle the event.target
s.
You have a number of syntax errors, but below is a working edit of your snippet.
To control the classes assigned to an element you need to use the classList
property of the element and its provided methods to add()
, remove()
or toggle()
a class.
const navBar = document.querySelector('.navbar__list');
const navElements = document.querySelectorAll('section');
navBar.addEventListener('click', function (event) {
event.preventDefault();
navBar.querySelector('.active')?.classList.remove('active');
event.target.classList.add('active');
});
navElements.forEach(function (section) {
const navlistElement = `<li class='menu__link ${section.className}' data-link=${section.id}><a href="#${section.id}">${section.dataset.nav}</li>`
navBar.insertAdjacentHTML('beforeend', navlistElement)
})
.active {
background-color: tomato;
}
<nav class="navbar__menu">
<!-- Navigation starts as empty UL that will be populated with JS -->
<ul class="navbar__list"></ul>
</nav>
<section id="section1" data-nav="Section 1" class="your-active-class">
<div class="landing__container">
<h2>Section 1</h2>
<p>Lorem ipsum dolor sit amet</p>
</div>
</section>
<section id="section2" data-nav="Section 2" class="your-active-class">
<div class="landing__container">
<h2>Section 2</h2>
<p>Lorem ipsum dolor sit amet</p>
</div>
</section>
Upvotes: 1