I have two component a Card component and a modal component, the modal component contains the modal Elements, in my Card component I would like to have a button which opens the modal Window of my modal component. How do I manage that, so far I have done this:
My Card component:
<template>
<v-layout v-if="visible">
<v-flex xs12 sm6 offset-sm3>
<v-card>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">test</h3>
<div>test</div>
</div>
</v-card-title>
<v-divider light></v-divider>
<v-card-actions>
<v-btn
color="primary"
dark
@click="dialog = true"
>
Open Dialog
</v-btn> <!-- open modal dialog of modal component? -->
<tenant-number-modal></tenant-number-modal>
</v-card-actions>
<input type="hidden" id="tenant-id" :value=tenantId>
</v-card>
</v-flex>
</v-layout>
</template>
<script>
export default {
data () {
return {
visible: true,
dialog: false,
uniqueTenantNumber: ''
}
},
}
</script>
My Modal component:
<template>
<v-layout row justify-center>
<v-btn
color="primary"
dark
@click="dialog = true"
> <!-- this calls the modal but only in this component -->
Open Dialog
</v-btn>
<v-dialog
v-model="dialog"
max-width="290"
>
<v-card>
<v-card-title class="headline">test</v-card-title>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
data () {
return {
dialog: false
}
}
}
</script>
Just add a $on function to the $root instance and call form any other component accessing the $root and calling $emit function. Save this answer.
Ref() and Reactive() are the new ways of creating reactive property introduced in Composition API Vue 3. They are wrapper objects that can be initialized with inner values and assigned to variables. In Vue 3, we need to import the desired package first before using it in the component.
Vue $emit is a function that lets us emit, or send, custom events from a child component to its parent. In a standard Vue flow, it is the best way to trigger certain events.
You can call a method of another component by using a ref
.
<v-card-actions>
<v-btn
color="primary"
dark
@click="openModal">
Open Dialog
</v-btn> <!-- open modal dialog of modal component? -->
<tenant-number-modal ref="modal"></tenant-number-modal>
</v-card-actions>
...
<script>
export default {
data () {
return {
//visible: true,
//dialog: false,
//uniqueTenantNumber: ''
}
},
methods: {
openModal() {
this.$refs.modal.showModal();
}
}
}
</script>
Your modal component:
<template>
<v-layout row justify-center>
...
<v-dialog
v-model="dialog"
max-width="290">
<v-card>
<v-card-title class="headline">test</v-card-title>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
data () {
return {
dialog: false
}
},
methods: {
showModal() {
this.dialog = true;
}
}
}
</script>
What you can do is create an event bus. This will allow you to send messages to 1+ components at once. Once you emit the message, then all components that are listening will execute.
First you need to create the bus:
bus.js
import Vue from 'vue';
export const EventBus = new Vue();
Next in the component that will emit the message you call EventBus.$emit(name, data)
componentA.js
import { EventBus } from './bus.js';
export default {
methods: {
emitGlobalClickEvent() {
EventBus.$emit('i-got-clicked', 'extra data');
}
}
}
Then in your other components, you just need to listen for the event. The following can be added to the component and you just need to use EventBus.$on(name, handle)
or if you only want to listen once use EventBus.$once(name, handle)
.
componentB.js
import { EventBus } from './bus.js';
export default {
created() {
EventBus.$on('i-got-clicked', data => {
console.log(data)
// You can then call your method attached to this component here
this.openModal()
});
},
methods: {
openModal() {
console.log('I am opening')
}
}
}
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