Search code examples
javascriptvuejs2vue-componentvuetify.js

Open a Vuetify dialog from a component template in VueJS


I'm using the VueJS Vuetify framework and I need to open a dialog - that gets imported as a component template - from another template. Once the Menu button in App.vue got clicked, the Modal should open. Here is my setup:

  • App.vue = navigation template with Menu button
  • Modal.vue = Modal template, imported as global in main.js

main.js

import Modal from './components/Modal.vue'
Vue.component('modal', Modal)

Modal.vue Template:

<template>
  <v-layout row justify-center>
    <v-btn color="primary" dark @click.native.stop="dialog = true">Open Dialog</v-btn>
    <v-dialog v-model="dialog" max-width="290">
      <v-card>
        <v-card-title class="headline">Use Google's location service?</v-card-title>
        <v-card-text>Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</v-card-text>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn color="green darken-1" flat="flat" @click.native="dialog = false">Disagree</v-btn>
          <v-btn color="green darken-1" flat="flat" @click.native="dialog = false">Agree</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </v-layout>
</template>
<script>
  export default {
    data () {
      return {
        dialog: false
      }
    }
  }
</script>

How to open the dialog?


Solution

  • You can open the dialog using custom events and using an event bus for non parent-child communication.

    If your application gets a bit more complex I recommend you use Vuex for state management.


    Event bus solution:

    In your main.js or in a new file create and export a new Vue instance :

    export const bus = new Vue()

    In app.vue import the busand emit the event:

    <template>
      <div>
        <button @click.prevent="openMyDialog()">my button</button>
      </div>
    </template>
    
    <script>
      import {bus} from '../main' // import the bus from main.js or new file
      export default {
        methods: {
          openMyDialog () {
            bus.$emit('dialog', true) // emit the event to the bus
          }
        }
      }
    </script>
    

    In modal.vue also import the bus and listen for the event in the created hook:

    <script>
      import {bus} from '../main'    
      export default {
        created () {
          var vm = this
          bus.$on('dialog', function (value) {
            vm.dialog = value
          })
        }
      }
    </script>