Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by NovaNomad979

How can I trigger the Child component's modal from a Parent button in Vue.js?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I have a Parent component with a button, and a Child component with a modal controlled by a reactive variable. I need to notify the Child to open its modal when the button is clicked in the Parent. I've provided sample code below for both components.

Parent.vue

VUE
<script setup> import Child from "Child.vue"; </script> <template> <button onClick=""> // open modal when button clicked <Child/> </template>

Child.vue

VUE
<script setup> import { ref } from "vue"; const openModal = ref(false); </script> <template> <div>example</div> </template>

Please let me know the best way to communicate from the Parent to the Child so the modal opens as expected. Any suggestions or improvements are appreciated.

3

Comments 0

Answers 3

Views 57

3 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

You can achieve this by having the Child component expose a method (for example, open()) and then use a template ref in the Parent to call that method when the button is clicked.

Below is one way to implement this:


Child.vue

VUE
<script setup> import { ref } from "vue"; // Reactive variable to track the modal state const openModal = ref(false); // Function to open the modal const open = () => { openModal.value = true; }; // Expose the open method so the parent can call it defineExpose({ open }); </script> <template> <!-- Show modal content only if openModal is true --> <div v-if="openModal"> example modal content </div> </template>

Parent.vue

VUE
<script setup> import { ref } from "vue"; import Child from "./Child.vue"; // Create a ref to store the child component instance const childRef = ref(null); const handleClick = () => { // Call the open method exposed by the Child component instance childRef.value?.open(); }; </script> <template> <!-- Call handleClick when the button is clicked --> <button @click="handleClick">Open Modal</button> <!-- Assign the template ref to the Child component --> <Child ref="childRef" /> </template>

Explanation

  1. Exposing the Method in the Child:
    In Child.vue, a method named open is defined to update the openModal reactive variable. This method is then exposed using defineExpose(), making it accessible from the Parent component.

  2. Using Template Refs in the Parent:
    In Parent.vue, a template ref (childRef) is created to reference the Child component. When the button is clicked, the handleClick function calls childRef.value.open(), which tells the Child to open the modal.

This approach ensures that both the logical relationship (Child handling its own modal state) and the required communication (Parent triggering the modal in Child) are maintained effectively.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by UranianVoyager647 1 month ago

0

An easy way to do this would be with props. If the parent has a ref isModalShown and the child takes this in as modelvalue, then the child can dynamically react to the state of that ref in the parent component, as well as mutate it directly. In script setup, it would look something like this:

In the parent:

VUE
<template> <button onclick="isModalShown = true">show</button> <Child v-model="isModalShown" /> </template> <script setup> const isModalShown = ref(false); </script>

and in the child:

VUE
<template> <MyModal v-model="isShown" /> </template> <script setup> const isShown = defineModel('modelValue'); function onClose() { isShown.value = false; // we can mutate the modelValue and the change will be emitted to the parent as an event, causing both components to update } </script>

This is core functionality of the Vue framework, and things like defineEmits would probably be best reserved for cases where we need to invoke methods of a child component, not just update a ref's value to be in sync with the parent.

No comments yet.

Answer by StarVoyager655 1 month ago

0

Sharing a variable with the parent

In the Child component, you can use defineExpose to send the status reactive variable accessible to the parent.

Example

or live CDN example:

Show code snippet

JAVASCRIPT
const { createApp, ref, defineExpose } = Vue; // Child const ChildComponent = { template: `< <div v-if="status"> <div> <p>Modal is open!</p> <button @click="closeModal">Close</button> </div> </div> `, setup() { const status = ref(false); const closeModal = () => { status.value = false; }; defineExpose({ status }); return { status, closeModal }; } }; // Parent const App = { components: { ChildComponent }, setup() { const childRef = ref(null); const openChildModal = () => { if (childRef.value) { childRef.value.status = true; } }; return { childRef, openChildModal }; } }; createApp(App).mount("#app");
HTML
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script> <div id="app"> <button @click="openChildModal">Open Modal</button> <child-component ref="childRef"></child-component> </div>

Run code snippetHide resultsExpand snippet

Notify the parent about an event

Nevertheless, I believe it is bad practice to extract a function from the component, as in the given example. A component should be self-contained, fully reusable at any time, and minimally affected by external factors. Therefore, I would place both the open and close buttons inside the child component, allowing the parent component to be informed about their clicks through emits.

You can call the emit from the child component, and when it is triggered, the parent component will be notified, allowing you to build custom functions in response.

Example

or live CDN example:

Show code snippet

JAVASCRIPT
const { createApp, ref, defineEmits } = Vue; // Child const ChildComponent = { template: `< <button v-if="! status" @click="openModal">Open Modal</button> <div v-if="status"> <div> <p>Modal is open!</p> <button @click="closeModal">Close</button> </div> </div> `, setup(_, { emit }) { const status = ref(false); const openModal = () => { status.value = true; emit('opened'); }; const closeModal = () => { status.value = false; emit('closed'); }; return { status, openModal, closeModal }; } }; // Parent const App = { components: { ChildComponent }, setup() { const customFnForChildOpen = () => { console.log('modal opened'); }; const customFnForChildClose = () => { console.log('modal closed'); }; return { customFnForChildOpen, customFnForChildClose }; } }; createApp(App).mount("#app");
HTML
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script> <div id="app"> <child-component @opened="customFnForChildOpen" @closed="customFnForChildClose"></child-component> </div>

Run code snippetHide resultsExpand snippet

No comments yet.

Discussion

No comments yet.