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:
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?
When I first answered this, I posted my answer as a "workaround", since it didn't felt completely "right" at the time and I was new to Vue.js. I wanted to open or close the dialog by using a v-model directive, but I couldn't get there. After a time I found how to do this in the docs, using the input event and the value property, and here's how I think it should be done without an event bus.
Parent component:
<template> <v-btn color="accent" large @click.stop="showScheduleForm=true"> <ScheduleForm v-model="showScheduleForm" /> </template> <script> import ScheduleForm from '~/components/ScheduleForm' export default { data () { return { showScheduleForm: false } }, components: { ScheduleForm } } </script>
Child component (ScheduleForm):
<template> <v-dialog v-model="show" max-width="500px"> <v-card> <v-card-actions> <v-btn color="primary" flat @click.stop="show=false">Close</v-btn> </v-card-actions> </v-card> </v-dialog> </template> <script> export default { props: { value: Boolean }, computed: { show: { get () { return this.value }, set (value) { this.$emit('input', value) } } } } </script>
I was able to work around this without the need for a global event bus.
I used a computed property with a getter AND a setter. Since Vue warns you about mutating the parent property directly, in the setter I simply emitted an event to the parent.
Here's the code:
Parent component:
<template> <v-btn color="accent" large @click.stop="showScheduleForm=true"></v-btn> <ScheduleForm :visible="showScheduleForm" @close="showScheduleForm=false" /> </template> <script> import ScheduleForm from '~/components/ScheduleForm' export default { data () { return { showScheduleForm: false } }, components: { ScheduleForm } } </script>
Child component (ScheduleForm):
<template> <v-dialog v-model="show" max-width="500px"> <v-card> <v-card-actions> <v-btn color="primary" flat @click.stop="show=false">Close</v-btn> </v-card-actions> </v-card> </v-dialog> </template> <script> export default { props: ['visible'], computed: { show: { get () { return this.visible }, set (value) { if (!value) { this.$emit('close') } } } } } </script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With