'Closing a dropdown navbar on click in JavaScript?

I've implemented a navbar using Bulma but I'm having trouble getting it to close after the user has clicked on an element inside the navbar. I have a single page setup so the page does not refresh, therefore the navbar doesn't "reset" and close.

Sorry if the answer is obvious or simple, I'm very new to JavaScript. I've attached a snippet of the code below.

document.addEventListener('DOMContentLoaded', () => {
    // Get all "navbar-burger" elements
    const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);

    // Check if there are any navbar burgers
    if ($navbarBurgers.length > 0) {

      // Add a click event on each of them
      $navbarBurgers.forEach( el => {
        el.addEventListener('click', () => {

          // Get the target from the "data-target" attribute
          const target = el.dataset.target;
          const $target = document.getElementById(target);

          // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
          el.classList.toggle('is-active');
          $target.classList.toggle('is-active');

        });
      });
    }
});

Any help would be greatly appreciated, thank you!



Solution 1:[1]

When elements get added to the DOM (in your case the .navbar-burgers) then you need to reattach the listeners. You could wrap your above javascript in a function and call it again when the content of your site has changed.

Or you specify a parent element which listens to a click event and check if the clicked target inside of it has a class .navbar-burger. E.g.:

document.addEventListener('DOMContentLoaded', () => {

    if (document.querySelector('.navbar-burger')) {
        document.querySelector('body').addEventListener('click', (el) => {
            if (el.currentTarget.classList.contains('.navbar-burger')) {
                // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
                el.classList.toggle('is-active');
                document.getElementById(el.getAttribute('data-target')).classList.toggle('is-active');
            }
        });
    }

});

In this example I specified body but I recommend you to be more specific. Because every click on your site will get into this event and checks if it is a navigation thing. However, the first option to reattach the listeners is a better practice.

Solution 2:[2]

I added an event listener on every navbar item to close the burger menu

item.addEventListener("click", () => {
    document.getElementById(burger_el.dataset.target).classList.remove('is-active');
    $target.classList.remove('is-active');
});

Here is the complete code I use to add the listeners for the burger menu:

document.addEventListener('DOMContentLoaded', () => {
    const navbarBurgers = document.querySelectorAll('.navbar-burger');
    const navbarItems = document.querySelectorAll(".navbar-item");

    navbarBurgers.forEach(burger_el => {
        burger_el.addEventListener('click', () => {
            // Toggle burger-menu
            document.getElementById(burger_el.dataset.target).classList.toggle('is-active');
            $target.classList.toggle('is-active');
        });
        navbarItems.forEach(item => {
            item.addEventListener("click", () => {
                // Close burger-menu
                document.getElementById(burger_el.dataset.target).classList.remove('is-active');
                $target.classList.remove('is-active');
            });
        });
    });
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 d2weber