Reputation: 665
I'm building simple modal component with Vue. I want to use this component in a parent components and to be able to toggle it from the parent.
This is my code now of the modal component:
<script>
export default {
name: 'Modal',
data() {
return {
modalOpen: true,
}
},
methods: {
modalToggle() {
this.modalOpen = !this.modalOpen
},
},
}
</script>
<template>
<div v-if="modalOpen" class="modal">
<div class="body">
body
</div>
<div class="btn_cancel" @click="modalToggle">
<i class="icon icon-cancel" />
</div>
</div>
</template>
I use the v-if to toggle the rendering and it works with the button i created inside my modal component.
However my problem is: I don't know how to toggle it with simple button from parent component. I don't know how to access the modalOpen data from the modal component
Upvotes: 1
Views: 2943
Reputation: 2070
With your current implementation I would suggest you to use refs https://v2.vuejs.org/v2/guide/components-edge-cases.html#Accessing-Child-Component-Instances-amp-Child-Elements
So in your parent component add ref="child"
to modal (child) component and then open your modal by calling this.$refs.child.modalToggle()
Upvotes: 1
Reputation: 339
Ok, let's try to do it right. I propose to make a full-fledged component and control the opening and closing of a modal window using the v-model in parent components or in other includes.
1) We need declare prop - "value" in "props" for child component.
<script>
export default {
name: 'Modal',
props: ["value"],
data() {
return {
modalOpen: true,
}
},
methods: {
modalToggle() {
this.modalOpen = !this.modalOpen
},
},
}
</script>
2) Replace your "modalToggle" that:
modalToggle() {
this.$emit('input', !this.value);
}
3) In parent components or other includes declare "modal=false" var and use on component v-model="modal" and any control buttons for modal var.
summary
<template>
<div v-if="value" class="modal">
<div class="body">
body
</div>
<div class="btn_cancel" @click="modalToggle">
<i class="icon icon-cancel" />
</div>
</div>
</template>
<script>
export default {
name: "Modal",
props: ["value"],
methods: {
modalToggle() {
this.$emit("input", !this.value);
}
}
};
</script>
Example:
Vue.component('modal', {
template: '<div v-if="value" class="modal"><div class="body">modal body</div><div class="btn_cancel" @click="modalToggle">close modal<i class="icon icon-cancel" /></div></div>',
props: ["value"],
methods: {
modalToggle() {
this.$emit('input', !this.value);
}
}
});
// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue({
el: '#app',
data:() =>({
modal: false
}),
methods: {
openModal() {
this.modal = !this.modal;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div @click="openModal">Btn modal</div>
<modal v-model="modal"></modal>
</div>
Upvotes: 2
Reputation: 4422
You can use an "activator" slot
You can use ref="xxx" on the child and access it from the parent
Upvotes: 0