Is there a lack of a multi-level dropdown menu in React JS similar to React-Bootstrap?

I have been using the following:

import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import NavDropdown from 'react-bootstrap/NavDropdown'

However, I am struggling to implement a Multi-Level Dropdown menu like this:

My-Menu
       menu-1
             menu-1-a
             menu-1-b   
       menu-2
       menu-3
            menu-3-a
            menu-3-b

Is there a Multi-Level Dropdown menu feature available in 'react-bootstrap' that I can incorporate?

Answer №1

To achieve this, you can utilize the following methods:

  1. recursiveMenu: Implements a dropdown menu recursively
  2. CustomToggle: Replicates the functionality of the original dropdown items
  3. render: Iterates through the items array

export const data = [
  {
    "_class": "leaf",
    "name": "Node"
  },
  {
    "_class": "submenu",
    "name": "Submenu",
    "children": [
      {
        "_class": "leaf",
        "name": "Node"
      },
      {
        "_class": "leaf",
        "name": "Node"
      }
    ]
  }
]

const recursiveMenu = (items, parent='') => {
  return (
    items.map(
      (o, i) => o._class !== 'submenu' ? (
        <Dropdown.Item key={`${i}/${o.name}`} onSelect={props.onSelect} id={`${parent}/${o.name}`}>{o.name}</Dropdown.Item>
      ) : o.children?.length > 0 ? (
        <Dropdown key={i} drop='right'>
          <Dropdown.Toggle as={CustomToggle} id="dropdown-basic">
            {o.name}
          </Dropdown.Toggle>
          <Dropdown.Menu>
            {recursiveMenu(o.children, `${parent}/${o.name}`)}
          </Dropdown.Menu>
        </Dropdown>
      ) : null
    )
  )
}

const CustomToggle = React.forwardRef(({ children, onClick }, ref) => (
  <a
    className="dropdown-item dropdown-toggle"
    href=""
    ref={ref}
    onMouseEnter={(e) => onClick(e)}
    onClick={(e) => {
      e.preventDefault();
      onClick(e);
    }}
  >
    {children}
  </a>
));

return (
  <Dropdown ref={ref}>
    <Dropdown.Toggle variant="success" id="dropdown-basic">
      {props.dataValue}
    </Dropdown.Toggle>
    <Dropdown.Menu>
      {recursiveMenu(data)}
    </Dropdown.Menu>
  </Dropdown>
)

Answer №2

Do you find what you are searching for? http://jsfiddle.net/n5u2wwjg/233886/

class DropdownMenu extends React.Component {

  getMenuItemTitle = (menuItem, index, depthLevel) => {
    return menuItem.title;
  };
 
  getMenuItem = (menuItem, depthLevel, index) => {
    let title = this.getMenuItemTitle(menuItem, index, depthLevel);

    if (menuItem.submenu && menuItem.submenu.length > 0) {
      return (
        <li>
          {title}
          <DropdownMenu config={menuItem.submenu} submenu={true} />
        </li>
      );
    } else {
      return <li>{title}</li>;
    }
  };

  render = () => {
    let { config } = this.props;

    let options = [];
    config.map((item, index) => {
      options.push(this.getMenuItem(item, 0, index));
    });

    if (this.props.submenu && this.props.submenu === true)
      return <ul>{options}</ul>;

    return <ul className="dropdown-menu">{options}</ul>;
  };
}


ReactDOM.render(<DropdownMenu config={[
    {
      "title": "Option 1",
      "submenu": null
    },
    {
      "title": "Option 2",
      "submenu": [
        {
          "title": "Option 2.1",
          "submenu": [
            {
              "title": "Option 2.1.1",
              "submenu": null
            },
            {
              "title": "Option 2.1.2",
              "submenu": null
            }
          ]
        },
        {
          "title": "Option 2.2",
          "submenu": [
            {
              "title": "Option 2.2.1",
              "submenu": null
            },
            {
              "title": "Option 2.2.2",
              "submenu": null
            }
          ]
        }
      ]
    }
  ]}/>, document.querySelector("#app"))
.dropdown-menu {
  height: 35px;
  list-style: none;
  margin: 0;
  padding: 0;
  float: left;
  text-align: center;
}

.dropdown-menu li {
  display: inline-block;
  position: relative;
  float: left;
  width: 200px;
  line-height: 35px;
  text-decoration: none;
}

.dropdown-menu li li a {
  font-size: 12px;
}

.dropdown-menu li:hover {
  background: blue;
}


/*--- Sublist Styles ---*/

.dropdown-menu ul {
  position: absolute;
  display: none;
}


/*--- Hide Sub Sublists ---*/

.dropdown-menu li:hover ul ul {
  display: none;
}


/*--- Sublevel UL's display and position on hover ---*/

.dropdown-menu li:hover ul {
  display: block;
}

.dropdown-menu li li:hover ul {
  margin-left: 200px;
  /*This must be width of menu box*/
  margin-top: -35px;
  display: block;
}

nu-li {
  padding: 10px;
}

.dropdown-submenu {
  position: absolute;
  left: 0px;
  top: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.3.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Answer №3

If you're looking to create a multi-level dropdown in React, there's a helpful package that can assist you with that. Check out this resource: https://github.com/SUPPLYcom/react-mega-menu

import ReactMegaMenu from "react-mega-menu"

<ReactMegaMenu 
   tolerance={50}      // optional, defaults to 100
   direction={"LEFT"}  
   styleConfig={...}  
   onExit={()=>{...}}
   data={[
  {
     label: "Category1",
     key: "Category1",
     items: "Category1 content"
  },
  {
     label: "Category2",
     key: "Category2",
     items: "Category2 content"
  },
  {
     label: "Category3",
     key: "Category3",
     items: "Category3 content"
   }
 ]}        // array of data to be rendered
/>

Here's a demo of what the output could look like:

https://i.sstatic.net/fcNU0.gif

https://i.sstatic.net/wQNLJ.gif

Imagine your final output resembling something like this:

https://i.sstatic.net/FwuMH.gif

This solution might prove valuable for someone in need.

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

Can you explain how this particular web service uses JSON to display slide images?

{ "gallery_images": [ {"img":"http://www.jcwholesale.co.uk/slider_img/big/1_1433518577.jpg"}, {"img":"http://www.jcwholesale.co.uk/slider_img/big/1_1433519494.jpg"}, {"img":"http://www.jcwholesale.co.uk/slider_img ...

What is the best way to align Bootstrap icons in the middle of buttons?

Currently, I am incorporating bootstrap icons into my design. Feel free to explore the provided DEMO. It showcases the issue of the bootstrap icons not aligning in the same line as the text inside the button. I am seeking advice on how to centralize the i ...

Learn how to connect a Firebase account that was created using a phone number

✅ I have successfully implemented the feature that allows users to update their profile with a mobile number using verifyPhoneNumber and update currentUser.updatePhoneNumber ❌ However, a problem arises when a new user attempts to sign in with a phone ...

Show the new elements added to an array in Angular without the need to refresh the page

I'm facing an issue where data added to an array is not being displayed on the browser, even though I can see it in the console. How can I ensure that the newly added data shows up without refreshing the screen in Angular? user.component.ts UserData: ...

Is it possible to hide the <dd> elements within a <dl> using knockout's custom data binding upon initialization?

I have implemented a <dl> where the <dd> can be expanded/collapsed by clicking on the corresponding <dt> using knockout's data binding. The inspiration for my solution came from a tutorial on creating custom bindings. Currently, I h ...

Node.js server side rendering encounters import file failure

In my current project, I am working on implementing server side rendering with React using TypeScript. All of the components, containers, and other directories are located within the src directory. When React imports a file from a location such as ./src/p ...

Creating a responsive design that adapts to various image sizes

In my API response, I am receiving images of various sizes. To display these images on my HTML page, I have created a table containing 4 images. To ensure responsiveness, I have set the width of the table to 100%, each row (tr) to 100%, each cell (td) to 2 ...

the background color for the menu on the page remains constant and does not alter

Check out this jsfiddle link for more information: http://jsfiddle.net/fht7zsm2/ To modify the background color of the current page, I utilized the following code: .sf-menu .active{ background-color:#1B3E70; color:white; ...

Retrieve the authentication token from OAuth2 using the ReactJS URL

I am seeking advice on the most effective way to generate a URL in React for receiving an Auth token in the query, which will be triggered through a redirect URL from the OAuth2 Authorization server. My current plan involves creating a component with a ro ...

Can you explain the process for setting the css property text-fill-color in IE and Mozilla browsers, similar to how I set -webkit-text-fill-color for Webkit?

The color displays correctly in Chrome, but how can I make it work in both IE and FF? CSS #Grid td.note div.has-note i { -webkit-text-fill-color: #b4efa8; } ...

Eliminate any undefined data in the popup map of Javascript

I am working with JSON data that is being displayed in a pop-up on a map. In cases where there is missing data (Visibility), the word undefined appears in the pop-up. Is there a way to remove the undefined text so that it does not show up in the pop-up? ...

A guide to removing functions from the render method

Greetings! Currently, I am in the process of creating a simple webpage that utilizes a map function to display all details to the user. Some fellow developers have advised me to remove my functions from the render method, as it continuously renders unneces ...

How to hide bullet points in a list when the links are hidden, utilizing either Jquery or CSS

In my attempt to hide bullet points from a list when links are hidden, the first and second links have been hidden using backend code in C#. I am trying to make sure that the bullets are only displayed if there are actual links present. <div class="l ...

Tips on rearranging appearance with z-index

My understanding of how z-index works seems to be a bit cloudy because I am facing difficulties reordering elements in this jsFiddle. I am trying to make the red box appear behind the text. Could someone provide guidance on how to achieve this? jsFiddle L ...

The alignment of the first and second steps in Intro.js and Intro.js-react is off

There seems to be an issue here. Upon reloading, the initial step and pop-up appear in the upper left corner instead of the center, which is not what I anticipated based on the Intro.js official documentation. https://i.stack.imgur.com/ICiGt.png Further ...

Having difficulty adjusting the width of a div element

I've been struggling to adjust the width of the div assigned with the colors class, whether in percentage or pixels. var colors = ["RED", "GREEN", "BLUE", "YELLOW", "PURPLE"]; for (var h = 0; h <= 4; h++) { for (var i = 0; i <= colors.lengt ...

Select and emphasize specific sections of text

Can I create an input element that looks like the one in my screenshot? I want to be able to change the value with JavaScript and highlight text by wrapping it with '*' and giving it a different color. Thank you for any assistance. ...

Unlocking the state of a recurring component in ReactJS

Just started learning reactjs. Currently, I am working on accessing the state of a repeated react component. Below is a snippet of my code: {Object.keys(this.state.sharing).map((share)=>{ return(<Sharings /> ...

Encountering an issue with Typescript Interfaces: property not found

This is my custom interface creation export interface UserInfo { success?: boolean, user?: User, employer?: Employer, hr?: Hr } After building this, the next task involves: let data = await loginUser(loginData); console.log(data.success); ...

translating creates vacant spaces on both sides

I am working with a <div class="scrollable"> that has the CSS property overflow: scroll;. Additionally, I have another <div class="line1"></div> which should not trigger any scrolling on the <div class="scrolla ...