7

I'm using BootstrapVue and I have a multi-level dropdown menu (with categories). This is an example from the official site:

https://bootstrap-vue.org/docs/components/dropdown

<b-dropdown id="dropdown-1" text="Dropdown Button" class="m-md-2">
  <b-dropdown-item>First Action</b-dropdown-item>
  <b-dropdown-item>Second Action</b-dropdown-item>
</b-dropdown>

But I don't know how to create a multi-level menu (I put dropdowns inside each other, but it doesn't work)! There's only a single-level dropdown example! How can I create a multi level one?

Thanks!

7
  • 1
    multi level is yet not supported by vue-bootstrap [github.com/bootstrap-vue/bootstrap-vue/issues/3435](Thread) Commented Aug 11, 2020 at 12:21
  • really ? what can i do about it ? :/ Commented Aug 11, 2020 at 12:25
  • Do you know which event is propagated thru this <b-dropdown Commented Aug 11, 2020 at 12:30
  • what ? what do you mean ? no i don't know about the events !!! Commented Aug 11, 2020 at 12:35
  • If you preventDefault event then you can nest b-dropdown inside b-dropdown Commented Aug 11, 2020 at 12:40

2 Answers 2

10

So as I mentioned in my comments you can wrap b-dropdown events and do something custom like this:

window.onload = () => {
  new Vue({
    el: '#app',
    data() {
      return {
        name: 'BootstrapVue',
        isDropdown2Visible: false
      }
    },
    mounted: function () {
      this.$root.$on('bv::dropdown::show', bvEvent => {
        if(bvEvent.componentId === 'dropdown-2') {
          this.isDropdown2Visible = true;
        }
        })
      this.$root.$on('bv::dropdown::hide', bvEvent => {
        if(bvEvent.componentId === 'dropdown-2') {
          this.isDropdown2Visible = false;
        }
        if(this.isDropdown2Visible) {
          bvEvent.preventDefault()
        }
        })
    }
  })
}
body { padding: 1rem; }
<link type="text/css" rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" />

<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>

<div id="app">
  <b-dropdown id="dropdown-1" text="Dropdown Button 1" class="m-md-2">
    <b-dropdown-item>First Action 1</b-dropdown-item>
    <b-dropdown-item>Second Action 1</b-dropdown-item>
    <b-dropdown id="dropdown-2" text="Dropdown Button 2" class="m-md-2">
        <b-dropdown-item>First Action 2</b-dropdown-item>
        <b-dropdown-item>Second Action 2</b-dropdown-item>
    </b-dropdown>
  </b-dropdown>
</div>

Sign up to request clarification or add additional context in comments.

Comments

1

You can try something like this

This snippet contains logic for one level menu.You can edit code as per your requirement

JSBin Link

new Vue({
  el: "#app",
  data: {
    menu: [
        { title : 'one'},
      { title : 'two'},
      { title : 'three',showSubMenu : false,
        children : [
          { title : 'four'},
          { title : 'five'},
      ]},
    ]  
  },
  methods : {       
    toogleItem(index){
      if(this.menu[index].children){
          if(!this.menu[index].showSubMenu){
            this.menu[index].showSubMenu = true
          } else {
            this.menu[index].showSubMenu = false
          }
      }
      
    }
  }
})
.sub-menu{
  position: absolute;            
    min-width: 10rem;
    padding: .5rem 0;
    margin: .125rem 0 0;
    font-size: 1rem;
    color: #212529;
    text-align: left;
    list-style: none;
    background-color: #fff;
    background-clip: padding-box;
    border: 1px solid rgba(0,0,0,.15);
    border-radius: .25rem;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />

<!-- Load polyfills to support older browsers -->
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>

<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>

<!-- Load the following for BootstrapVueIcons support -->
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
</head>
<body>

<div id="app">  
  <b-dropdown id="dropdown-1" text="Dropdown Button" class="m-md-2">
    <b-dropdown-item 
     v-for="(item,index) in menu"  
     :key="index"
     @mouseover.native="toogleItem(index)"
     @mouseout.native="toogleItem(index)">
      <span>{{item.title}} <b-icon-caret-down-fill :scale="0.6" v-if="item.children"></b-icon-caret-down-fill></span>
        <div v-if="item.children" class="sub-menu" v-show="item.showSubMenu">
            <b-dropdown-item v-for="(item,index) in item.children" :key="index">{{item.title}}
            </b-dropdown-item>   
        </div>
    </b-dropdown-item>   
  </b-dropdown>
</div>
</body>
</html>

2 Comments

Doesn't look to work with keyboard only navigation, so someone using something like a screenreader might not be able to access the nested dropdown.
@Hiws this is just hack to things get work.if need to consider touch support then need to do additional stuff

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.