vue.jsvuetify.jsv-dialog

How to use Vuetify v-dialog isActive to load a function everytime it is changed to true


I am trying to make my components a little more compact and modular and that means encapsulating a v-dialog component and its internal items. This v-dialog is activated from the parent component with the click event as shown:

        <v-menu location="bottom">
          <template v-slot:activator="{ props }">
            <v-btn class="mx-3" icon="mdi-dots-horizontal" size="small" color="primary" v-bind="props" variant="tonal"/>
          </template>
          <v-list>
            <v-list-item link>
              <v-list-item-title>Draft Acknowledgement Email</v-list-item-title>
            </v-list-item>
            <v-list-item link>
              <v-list-item-title>Process Upload
                <EmailFilesAssignment :emails="selectedEmails" :mailbox="activeMailboxLabel"/>
              </v-list-item-title>
            </v-list-item>
          </v-list>
        </v-menu> 

Then the component is as follows:

<template>
  <v-dialog activator="parent" max-width="800">
    <template v-slot:default="{ isActive }">
      <v-card rounded="lg">
        <v-card-title class="d-flex justify-space-between align-center">
          <div class="text-h5 text-medium-emphasis ps-2">
            Assign Files For Upload
          </div>

          <v-btn
            icon="mdi-close"
            variant="text"
            @click="isActive.value = false"
          ></v-btn>
        </v-card-title>


        <v-card-actions class="my-2 d-flex justify-end">
          <v-btn
            class="text-none"
            rounded="xl"
            text="Cancel"
            @click="isActive.value = false"
          ></v-btn>

          <v-btn
            class="text-none px-5 mx-3"
            color="primary"
            rounded="xl"
            text="Begin Upload Process"
            variant="flat"
            @click="isActive.value = false"
          ></v-btn>
        </v-card-actions>
      </v-card>
    </template>
  </v-dialog>
</template>

The issue is I have some functions in my child component such as loadData() that is run when the child component is registered so it only runs once and actually seems to run when the v-menu is activated not when the v-dialog is activated. I need to tap into isActivated to run loadData() when this becomes true so I get a fresh reload every time as additional stuff is into the child component from this.


Solution

  • Listen for update:modelValue event that is emitted from v-dialog whenever it opens or closes. The event parameter is a boolean with the status of the dialog (true if opened, false if closed). Simplified version:

    <template>
      <v-container>
        <v-btn>
          Parent Activator
          <v-dialog
            activator="parent"
            @update:model-value="dialogUpdate"
          >
            <template v-slot:default="{ isActive }">
              <v-card text="test" title="Title">
                <template v-slot:actions>
                  <v-btn
                    text="Close"
                    @click="isActive.value = false"
                  ></v-btn>
                </template>
              </v-card>
            </template>
          </v-dialog>
        </v-btn>
      </v-container>
    </template>
    
    <script setup>
      const emit = defineEmits(['dialogOpened'])
    
      function dialogUpdate(isOpen) {
        if (isOpen) {
          console.log('dialog is open')
          // if need to know in parent
          emit('dialogOpened')
        }
      }
    </script>
    

    Vuetify Playground example