nested dropdowns in Bootstrap 4

I'm currently working on a nested dropdown menu feature. Although I have successfully implemented the functionality to display the next level, I am facing an issue where it does not close upon clicking.

Check out my code here!

Here is the JavaScript snippet:

 const nodeList = document.querySelectorAll('.dropdown-menu a.dropdown-toggle');
    nodeList.forEach((elem) => {
      elem.addEventListener('click', (e) => {
      e.stopPropagation();
        let parent = elem.offsetParent;
        if (!elem.nextElementSibling.classList.contains('show')) {
          parent.classList.remove('show');
        }

        let subMenu = elem.nextElementSibling;
        console.log(subMenu);
        subMenu.classList.toggle('show');
        elem.parentElement.classList.toggle('show');
        console.log(elem.parentElement);
      });
    });

Answer №1

If you're only using one dropdown menu and experiencing issues with the initial menu button, try removing the .dropdown-menu class to see if that resolves the problem.

To ensure that submenus close when their parent is closed, you'll need to loop through each submenu individually. Take a look at the code snippet below for an example of how this can be achieved:

const nodeList = document.querySelectorAll('a.dropdown-toggle');
nodeList.forEach((elem) => {
  elem.addEventListener('click', (e) => {
    e.stopPropagation();
    
    let subMenu = elem.nextElementSibling;
    console.log(subMenu);
    subMenu.classList.toggle('show');
    if (!subMenu.classList.contains('show')) {
      let menusToClose = subMenu.querySelectorAll('ul.dropdown-menu');
      menusToClose.forEach((menuToClose) => {
      menuToClose.classList.remove('show');
      });
    }
  });
});
/*//Copy this css*/

.navbar-light .navbar-nav .nav-link {
  color: rgb(64, 64, 64);
}

.btco-menu li>a {
  padding: 10px 15px;
  color: #000;
}

.btco-menu .active a:focus,
.btco-menu li a:focus,
.navbar>.show>a:focus {
  background: transparent;
  outline: 0;
}

.dropdown-menu .show>.dropdown-toggle::after {
  transform: rotate(-90deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<!-- Static navbar -->
<nav class="navbar navbar-expand-md navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <ul class="navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Features</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Pricing</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                Dropdown link
                            </a>
        <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <li><a class="dropdown-item" href="#">Action</a></li>
          <li><a class="dropdown-item" href="#">Another action</a></li>
          <li><a class="dropdown-item dropdown-toggle" href="#">Submenu</a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#">Submenu action</a></li>
              <li><a class="dropdown-item" href="#">Another submenu action</a></li>

              <li><a class="dropdown-item dropdown-toggle" href="#">Subsubmenu</a>
                <ul class="dropdown-menu">
                  <li><a class="dropdown-item" href="#">Subsubmenu action aa</a></li>
                  <li><a class="dropdown-item" href="#">Another subsubmenu action</a></li>
                </ul>
              </li>
              <li><a class="dropdown-item dropdown-toggle" href="#">Second subsubmenu</a>
                <ul class="dropdown-menu">
                  <li><a class="dropdown-item" href="#">Subsubmenu action bb</a></li>
                  <li><a class="dropdown-item" href="#">Another subsubmenu action</a></li>
                </ul>
              </li>
            </ul>
          </li>
          <li><a class="dropdown-item dropdown-toggle" href="#">Submenu 2</a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#">Submenu action 2</a></li>
              <li><a class="dropdown-item" href="#">Another submenu action 2</a></li>

              <li><a class="dropdown-item dropdown-toggle" href="#">Subsubmenu</a>
                <ul class="dropdown-menu">
                  <li><a class="dropdown-item" href="#">Subsubmenu action 1 3</a></li>
                  <li><a class="dropdown-item" href="#">Another subsubmenu action 2 3</a></li>
                </ul>
              </li>
              <li><a class="dropdown-item dropdown-toggle" href="#">Second subsubmenu 3</a>
                <ul class="dropdown-menu">
                  <li><a class="dropdown-item" href="#">Subsubmenu action 3 </a></li>
                  <li><a class="dropdown-item" href="#">Another subsubmenu action 3</a></li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</nav>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

jquery global variable not working as expected

I'm having trouble making some variables global outside the jQuery function. I've tried using 'var' to declare them first and then assigning values, but when I try to log() them at the end, I get undefined. var lat, lon; $.get('ip ...

Loop through an array of elements in JavaScript and retrieve the element with the largest pixel size

I am facing a challenge with elements positioned absolutely on a web page. My goal is to iterate over these elements and identify the one with the highest top value. I attempted two different approaches: const elems = document.querySelectorAll('.ind ...

Tallying discarded objects post removal from drop zone

Is there a way to accurately count dropped items within a dropped area? I have created an example that seems to be working fine but with one minor issue. When I begin removing items, the count does not include the first item and only starts decreasing afte ...

Using Reactjs to create a custom content scroller in jQuery with a Reactjs twist

I am attempting to implement the Jquery custom scrollbar plugin here in my React project. Below is a snippet of my code: import $ from "jquery"; import mCustomScrollbar from 'malihu-custom-scrollbar-plugin'; ..... componentDidMount: function() ...

Combining two request.get functions into a single one

Is there a way to combine these two functions into one? I have two APIs: /page1 and /page2. My goal is to merge the two arrays into one because the GitHub API only displays 100 objects per page. request.get({ url: 'https://api.github.com/users/an ...

Obtaining form data from connected drop-down menus and sending it to PHP

My webpage contains a form with 2 dependent drop-down lists. When a user selects a value from the first list, it populates the second list for the user to make another selection. However, when I try to submit the form data to a PHP page to insert into a M ...

Guide to utilizing axios.request(config) in Vue.js

I have been attempting to use Axios in my vue.js project to make HTTP requests. Despite reviewing the Axios documentation on GitHub and exploring various examples online, I have yet to find a solution. My goal is to create a configuration file where I can ...

Executing the command `npm run jshint` yields the error message `script not found: jshint`

Currently, I'm attempting to run jshint on a few javascript files. However, I am encountering an issue where the local npm install of jshint is not functioning as expected. Upon checking, the package is indeed present: $ npm list --depth=0 <a hre ...

What is the best way to append something to the textContent property of an HTML tag within a markup page?

While working on resolving an XSS vulnerability in the jqxGrid where the cell content is rendered as HTML, I encountered a scenario like this: <a href="javascript:alert('test');">Hello</a>. To address this issue, I am exploring ways t ...

What sets array of middlewares apart from compose-middleware?

Someone recommended that I utilize the compose-middleware module in order to have an array of middlewares. After trying it out, I discovered that it works seamlessly with express.js: router.post('/editPassword', doAction ); var doAction = [ ...

Is there a way to prevent Material-UI SpeedDial from automatically closing when a SpeedDialAction button is clicked?

Looking to customize the functionality of Material-UI's SpeedDial component (https://material-ui.com/api/speed-dial/). At present, when a SpeedDialAction is clicked, the main SpeedDial component automatically closes. I want to modify this behavior s ...

Unable to differentiate between .jsx and .js files

Here is the content of my JavaScript file: var React = require('react'); export default class AmortizationChart extends React.Component { render() { var items = this.props.data.map(function (year, index) { ret ...

Exploring the Power of jQuery Deferreds and Promises through Multiple getJSON Requests

I'm currently exploring the concept of jquery deferred/promises. I have a decent grasp on how to handle one ajax call, but I'm struggling with managing multiple ajax calls simultaneously. Here is a link to a jsfiddle showcasing my attempt: http:/ ...

Storing keys and multiple maps with React applications

Having a multiple array with an option set created, everything is functioning correctly const groups1 = OrgServices.reduce((all, cur) => ((all[cur.grouptype] ??= []).push(...cur.servicetype), all), {}); const output1 = Object.entries(groups1).map ...

Pause and continue scrolling through the page with the push of a button

I have a question about a simple demo. I am looking to prevent scrolling when button1 is clicked, and then resume scrolling when button2 is clicked. Can someone guide me on how to achieve this? Check out the Fiddle here HTML: <input type='button& ...

What is the process for updating the list to retrieve fresh data from the service?

I am currently in the process of calling a web service to retrieve data and display it in a list using directives. Upon loading my fiddle, I successfully load data from a JSON file. The data is displayed correctly in the list. If I click the delete butto ...

What is the best way to transform a JavaScript object into an array?

Here is the information I have: {product_quantity: {quantity: 13, code: "AAA", warehouse: "1000",}} The product_quantity field is part of a JSON object in a MongoDB database. I am looking to convert it into this format: {"produ ...

Enhancing data management with Vuex and Firebase database integration

Within my app, I am utilizing Firebase alongside Vuex. One particular action in Vuex looks like this: async deleteTodo({ commit }, id) { await fbs.database().ref(`/todolist/${store.state.auth.userId}/${id}`) .remove() .then ...

How can I make the row color of a jQuery datatable change when the row is selected?

One of my challenges involves implementing a jquery dataTable (view here) where each row contains a checkbox. I want the row's color to change when the checkbox is checked. This is the approach I attempted: <table id="tabellaOrdinaFarmaci" class=" ...

Is there a way to randomly rearrange an array of objects when the page loads, then iterate over the rearranged array without triggering a console warning about "two children with the same key"?

When shuffling the array and mapping over it in my application, I am able to correctly display the shuffled data using translate3d for a slider effect. However, I keep receiving a growing list of console warnings: "Encountered two children with the s ...