Trigering methods in nested VUE 3 components

Viewed 66

I have a simple app. Clicking to [new item] links opens a child component which has a modal window component for user input.

What is the best way to open modal from the App component. I am not also sure this design is the best approach. I used to manage this with Classes and Methods when I was using native js. But in VUE accessing sub components methods via an interface is a pain. All I want to do is to open a new item model anywhere in the app.

Structure:

|--App.vue
|  |--NewItem.vue
|  |  |--Modal.vue

App.vue:

<template>
   <a @click="openNewItem()"> + NEW ITEM</a>   
   ... 
   <a @click="openNewItem()"> + NEW ITEM</a>   
   ... 
   //Create new Item link appears at multiple places in app
   <NewItem />
</template>

<script setup>
conts openNewItem=()=>{
 //....
}
</script>

NewItem.vue:

<template>
   <Modal v-model:visible="dialogOpen">
        <template v-slot:title>New Item</template>
        <template v-slot:content >           
               <input type="text" class="lg" />
               <button @click="create()">ADD ITEM</button>                 
        </template>
    </Modal> 
</template>

<script setup>
import {  ref} from "vue";
import Modal from "./Modal.vue"; 

const dialogOpen=ref(false);
const create=()=>{
    //logic...
    console.log("create item");
    //close modal...
    dialogOpen.value=false
}
</script>

Modal.vue:

<template >
    <template v-if="isVisible" >
        <div class="overlay"><!-- overlay --></div>
        <section>
            <div class="main"  v-bind="$attrs" >
                <div class="head">
                    <div class="title">
                        <slot name="title"></slot>
                    </div>
                    <div>
                        <a @click="close()">✖</a>
                    </div>
                </div>
                <div class="content">
                    <slot name="content"></slot>
                </div>
            </div>
        </section>
    </template>
</template>

<script setup>
import { computed } from "vue";

const props = defineProps({ 
    visible: Boolean
});

const emit = defineEmits(["update:visible"]);
const isVisible = computed({
    get: () => props.visible,
    set: (value) => {
        emit("update:visible", value);
    },
});
const close = () => {
    isVisible.value = false
}
</script>
1 Answers

You can try to add the modal in the App.vue and created a global variable to control its visibility. In case if you have more components, you can just it to parent component of all components (or particular page)

Related