How To Show Only One V-Menu At A Time When Clicking To Show The Menu?

In Vuetify applications, showing only one v-menu at a time when clicking requires proper state management. This prevents multiple menus from being open simultaneously and provides better user experience.

Understanding v-menu Behavior

By default, v-menu components can open independently. To ensure only one menu is visible at a time, we need to control their state using Vue's data properties and watchers.

Method 1: Using Individual State Control

This approach manages each menu's state individually and closes others when one opens:

<!DOCTYPE html>
<html>
<head>
   <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
   <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
   <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
</head>
<body>
   <div id="app">
      <v-app>
         <v-container>
            <div style="display: flex; gap: 20px; align-items: center;">
               <v-menu 
                  v-for="(user, index) in userInfo" 
                  :key="index" 
                  v-model="menuStates[index]"
                  @input="onMenuToggle(index, $event)"
                  offset-y>
                  <template v-slot:activator="{ on, attrs }">
                     <v-btn v-bind="attrs" v-on="on" color="primary">
                        {{user.name}}
                     </v-btn>
                  </template>
                  <v-list>
                     <v-list-item>
                        <v-list-item-content>
                           <v-list-item-title>Favorite Car: {{user.favoritecar}}</v-list-item-title>
                        </v-list-item-content>
                     </v-list-item>
                  </v-list>
               </v-menu>
            </div>
         </v-container>
      </v-app>
   </div>

   <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
   <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
   <script>
      new Vue({
         el: '#app',
         vuetify: new Vuetify(),
         data() {
            return {
               userInfo: [
                  { id: 1, name: "Alice", favoritecar: "RX100" },
                  { id: 2, name: "Bob", favoritecar: "DUCATI" },
                  { id: 3, name: "Charlie", favoritecar: "RANGEROVER" }
               ],
               menuStates: [false, false, false]
            };
         },
         methods: {
            onMenuToggle(index, isOpen) {
               if (isOpen) {
                  // Close all other menus
                  this.menuStates.forEach((state, i) => {
                     if (i !== index) {
                        this.$set(this.menuStates, i, false);
                     }
                  });
               }
            }
         }
      });
   </script>
</body>
</html>

Method 2: Using Single Active Menu State

This cleaner approach tracks which menu is currently active using a single variable:

<!DOCTYPE html>
<html>
<head>
   <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
   <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
   <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
</head>
<body>
   <div id="app">
      <v-app>
         <v-container>
            <div style="display: flex; gap: 20px; align-items: center;">
               <v-menu 
                  v-for="(item, index) in menuItems" 
                  :key="index" 
                  :value="activeMenu === index"
                  @input="toggleMenu(index, $event)"
                  offset-y>
                  <template v-slot:activator="{ on, attrs }">
                     <v-btn v-bind="attrs" v-on="on" :color="activeMenu === index ? 'success' : 'primary'">
                        {{item.label}}
                     </v-btn>
                  </template>
                  <v-list>
                     <v-list-item v-for="option in item.options" :key="option">
                        <v-list-item-content>
                           <v-list-item-title>{{option}}</v-list-item-title>
                        </v-list-item-content>
                     </v-list-item>
                  </v-list>
               </v-menu>
            </div>
         </v-container>
      </v-app>
   </div>

   <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
   <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
   <script>
      new Vue({
         el: '#app',
         vuetify: new Vuetify(),
         data() {
            return {
               activeMenu: null,
               menuItems: [
                  { label: "Menu 1", options: ["Option A", "Option B"] },
                  { label: "Menu 2", options: ["Choice 1", "Choice 2"] },
                  { label: "Menu 3", options: ["Item X", "Item Y"] }
               ]
            };
         },
         methods: {
            toggleMenu(index, isOpen) {
               this.activeMenu = isOpen ? index : null;
            }
         }
      });
   </script>
</body>
</html>

Comparison

Method Data Management Complexity Best For
Individual State Control Array of booleans Medium Complex menu interactions
Single Active State Single variable Low Simple one-at-a-time behavior

Key Points

  • Use v-model or :value with @input to control menu visibility
  • Track active menu state in Vue data
  • Close other menus when one opens using event handlers
  • The single active state approach is cleaner for most use cases

Conclusion

Implementing one-at-a-time v-menu behavior requires proper state management. The single active menu approach offers the cleanest solution for most applications, ensuring better user experience by preventing menu overlap.

Updated on: 2026-03-15T23:19:01+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements