简体   繁体   中英

ReactJS multi level dropdown menu

I'm trying to build a multi level ReactJs dropdown menu. I'm using the following post/code as base: the following post and this jsfiddle code as starting point of my ReactJs component:

class DropdownMenu extends Component {
  static propTypes = {
    config: PropTypes.array.isRequired
  };

  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>;
  };
}

export default DropdownMenu;

CSS file:

.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;
}

.dropdown-menu li a {
    display: inline-block;
    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;
    margin-top: -35px;
    display: block;
}
nu-li {
    padding: 10px;
}

.dropdown-submenu {
    position: absolute;
    left: 0px;
    top: 0px;
}

And finally my configuration file:

  "navItems": [
    {
      "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
            }
          ]
        }
      ]
    }
  ]

I'm getting a messy menu, with options above other options and I'm sure I'm missing something simple.

How can I turn my component in a real multi level dropdown menu?

This questions is getting old, but for the sake of clearity, I added a jsfiddle to your question . For fiddle to work with your code i had to remove your propTypes and used internal props in ReactJS, see more here and then render it directly instead of exporting it.

I then saw the menu being a bit weird where the width of the menu item's was not sat, so i changed this:

.dropdown-menu li {
    display: inline-block;
    position: relative;
    float: left;
}

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

to this:

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

However, I dont see your messy menu let me know if you still have problems.

I quickly modified the code of Lagoni, so that it also get and displays the depth of the submenu.

It gets it from the props and increments it at each recursion:

<DropdownMenu config={menuItem.submenu} depthLevel={depthLevel+1} submenu={true} />`

This way, you can effectively use it to, for instance, set the class according to the depth level. For example, make a gradient of color every time you go deeper, or increase the indentation.

jsfiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM