Multi-Level Dropdown menu in react js is not available or what? Like react-bootstrap

10,410

Solution 1

Is it what you're looking? 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>

Solution 2

It can be achieved using:

  1. recursiveMenu: Embeds a dropdown menu
  2. CustomToggle: Mimics the original dropdown items
  3. render: Traverses 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>
  )
Share:
10,410
Thokchom Rajesh
Author by

Thokchom Rajesh

Updated on June 24, 2022

Comments

  • Thokchom Rajesh
    Thokchom Rajesh almost 2 years

    I am using the below

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

    but I can't able to find to do Multi-Level Dropdown menu like

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

    is there Multi-Level Dropdown menu in 'react-bootstrap' that I can use please.