Search code examples
javascriptdrop-down-menunavbarbootstrap-5

Bootstrap Navbar Toggler - Custom JS causes navbar menu to close on dropdown click


I'm new to JS and am in the process of learning while coding a website. I'm using a template that I found online with some custom modifications so I'm not super familiar with the JS used. Here is the issue.

While using the navbar toggler there is some custom JS to close the menu when the once a click happens in the menu. The issue is that I added a dropdown into the menu, and when it's clicked instead of showing the drop down details, the JS executes and closes the menu. here is the JS:

window.addEventListener('DOMContentLoaded', event => {

// Navbar shrink function
    var navbarShrink = function () {
        const navbarCollapsible = document.body.querySelector('#mainNav');
        if (!navbarCollapsible) {
           return;
        }
        if (window.scrollY === 0) {
            navbarCollapsible.classList.remove('navbar-shrink')
        } else {
            navbarCollapsible.classList.add('navbar-shrink')
        }

    };

// Shrink the navbar 
    navbarShrink();

// Shrink the navbar when page is scrolled
    document.addEventListener('scroll', navbarShrink);

// Activate Bootstrap scrollspy on the main nav element
    const mainNav = document.body.querySelector('#mainNav');
    if (mainNav) {
        new bootstrap.ScrollSpy(document.body, {
            target: '#mainNav',
            offset: 74,
        });
    };

// Collapse responsive navbar when toggler is visible
    const navbarToggler = document.body.querySelector('.navbar-toggler');
    const responsiveNavItems = [].slice.call(
        document.querySelectorAll('#navbarResponsive .nav-link')
    );

    responsiveNavItems.map(function (responsiveNavItem) {
        responsiveNavItem.addEventListener('click', () => {
            if (window.getComputedStyle(navbarToggler).display !== 'none') {
                navbarToggler.click();
            }
        });
    });

});

Only the bottom function is running the menu click/close function, but I provided all the code as for the custom menu actions as I'm not super familiar with JS. I understand, more or less, what it is doing, but I'm not sure how to modify it appropriately.

I'd imagine there is a simple way to modify that last "if" statement to check to see what was actually clicked (for example, if a .dropdown-menu was clicked). I just don't know how to use the code that is there and check what click caused the event trigger. I'd like to keep the close behavior when the .dropdown-items and other .nav-items are clicked. I just don't want the behavior when the .dropdown-menu is clicked.

Here is the html:

<div class="collapse navbar-collapse" id="navbarResponsive">
    <ul class="navbar-nav text-uppercase ms-auto py-4 py-lg-0">
       <li class="nav-item"><a class="nav-link" href="#portfolio">Products</a></li>
       <li class="nav-item"><a class="nav-link" href="#services">Services</a></li>
       <li class="nav-item"><a class="nav-link" href="#how-to-order">How Order</a></li>
       <li class="nav-item dropdown"><a class="nav-link dropdown-toggle" data-bs-toggle="dropdown"  role="button" aria-expanded="false">F.A.Q.</a>
           <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton2">
                <li><a class="dropdown-item" href="#">Knowledge Base</a></li>
                <li><hr class="dropdown-divider"></li>
                <li><h4 class="dropdown-header">Most Common Questions:</h4></li>
                <li><a class="dropdown-item" href="#">Where are you located</a></li>
                <li><a class="dropdown-item" href="#">How long is shipping</a></li>
                <li><a class="dropdown-item" href="#">How do I pay</a></li>
                <li><hr class="dropdown-divider"></li>
           </ul>
       </li>
       <li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
    </ul>
 </div>

I'm pretty sure this is a super simple JS problem that any coder worth his $.02 would know, but not knowing JS I don't even know where or what to search for. Any help?


Solution

  • The issue with your code is that when you are using querySelectorAll to access the nav-links the code is trying to access all the nav-links i.e., you are considering all the nav-links then the dropdown in your nav which is also a nav-link is also considered. So the better way to solve this is you can create a new class and attach it to the dropdown nav-link in your case F.A.Q and exclude that class from the function.

    Your code:

    <li class="nav-item dropdown"><a class="nav-link dropdown-toggle" data-bs-toggle="dropdown"  role="button" aria-expanded="false">F.A.Q.</a>
      <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton2">
        <li><a class="dropdown-item" href="#">Knowledge Base</a></li>
        <li><hr class="dropdown-divider"></li>
        <li><h4 class="dropdown-header">Most Common Questions:</h4></li>
        <li><a class="dropdown-item" href="#">Where are you located</a></li>
        <li><a class="dropdown-item" href="#">How long is shipping</a></li>
        <li><a class="dropdown-item" href="#">How do I pay</a></li>
        <li><hr class="dropdown-divider"></li>
      </ul>
    </li>
        
    const responsiveNavItems = [].slice.call(
      document.querySelectorAll('#navbarResponsive .nav-link')
    );
    

    You can add a class called faq and exlude it from the querySelectorAll using :not()

    <!-- added a new class faq to the dropdown link -->
    <li class="nav-item dropdown"><a class="nav-link dropdown-toggle faq" data-bs-toggle="dropdown"  role="button" aria-expanded="false">F.A.Q.</a>
      <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton2">
        <li><a class="dropdown-item" href="#">Knowledge Base</a></li>
        <li><hr class="dropdown-divider"></li>
        <li><h4 class="dropdown-header">Most Common Questions:</h4></li>
        <li><a class="dropdown-item" href="#">Where are you located</a></li>
        <li><a class="dropdown-item" href="#">How long is shipping</a></li>
        <li><a class="dropdown-item" href="#">How do I pay</a></li>
        <li><hr class="dropdown-divider"></li>
      </ul>
    </li>
    
    // select all links except faq class
    const responsiveNavItems = [].slice.call(
        document.querySelectorAll('#navbarResponsive a.nav-link:not(.faq)')
    );