skip to Main Content

I’m trying to create a Dialog component and use it into another component.
When I click the button, the Dialog opens, but I don’t know how to close it.
These are the components:

Dialog:

<template>
  <Dialog
    header="###"
    :visible="displayModal"
    :breakpoints="{ '960px': '75vw', '640px': '90vw' }"
    :style="{ width: '50vw' }"
    :modal="true"
  >
    <div class="container">
      // Dialog content
    <template #footer>
      <Button
        label="Close"
        class="p-button p-button-secondary"
        icon="pi pi-times"
        @click="closeModal"
      />
      <Button
        label="Guardar"
        class="p-button p-button-primary"
        icon="pi pi-check"
        autofocus
        v-model:visible="displayModal"
      />
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { defineEmits, ref } from "vue";

defineEmits(["update:visible"]);
const displayModal = ref(false);
const closeModal = () => {
  displayModal.value = false;
};

</script>

The other component:

<template>
     // Some code
        <SplitButton
          class="datatable-button"
          icon="pi pi-pencil"
          label="XXX"
          :model="XXX"
          @click="openModal"
        />
    <ModalDialog v-model:visible="displayModal" />
  </div>
</template>

<script setup lang="ts">
import ModalDialog from "@/components/modal/ModalDialog.vue";
import { ref } from "vue";
//Modal
const displayModal = ref(false);

const openModal = () => {
  displayModal.value = true;
  console.log("DisplayModal: ", displayModal.value);
};
</script>

I’ve tried using emits but i’m not sure how to do it.

2

Answers


  1. Chosen as BEST ANSWER

    I've already solved doing this: All the logic belongs to the parent, the child only emits the event.

    Parent:

      <template>
        <ModalDialog
          :visible="displayModal"
          @close-modal="closeModal"
        />
      </template>
        
      <script setup lang "ts">
        const displayModal = ref(false);
        
        const openModal = () => {
          displayModal.value = true;
        };
        
        const closeModal = () => {
          displayModal.value = false;
        };
      </script>
    

    Child:

      <template>
        <Dialog :visible="visible">
        //some code
        </Dialog>
      <template>
    
      <script setup lang="ts">
        const emit = defineEmits(["closeModal"]);
        
        defineProps({
          visible: {
          type: Boolean,
          },
        });
        
        const closeModal = () => {
          emit("closeModal");
        };
      </script>
    

  2. Replace your closeModal with

    const closeModal = () => {
      emit("update:visible", false);
    };
    

    And add by ModalDialog v-on @update:visible="closeDialog($event)"

      const closeDialog = (value) => {
        displayModal.value = value;
        console.log("DisplayModal: ", displayModal.value);
      };
    

    Playground

    const {createApp, ref, defineProps, defineEmits } = Vue;
    
    const ModalDialog = {
      components: {
          'p-button': primevue.button,
          'p-dialog': primevue.dialog
      },
      props: ['visible'],
      setup(props, { attrs, slots, emit, expose }) {
        defineEmits(["update:visible"]);
        const closeModal = () => {
          emit("update:visible", false);
        };
         return {
              closeModal
         };
      },
      template: '#modal-dialog'
    }
    
    const App = {
      setup() {
          const displayModal = ref(false);
          const openModal = () => {
            displayModal.value = true;
            console.log("DisplayModal: ", displayModal.value);
          };
          const closeDialog = (value) => {
            displayModal.value = value;
            console.log("DisplayModal: ", displayModal.value);
          };
          return {
              displayModal, openModal, closeDialog
          };
      },
      components: {
          ModalDialog,
          'p-button': primevue.button,
          'p-dialog': primevue.dialog
      }
    };
    
    createApp(App).use(primevue.config.default).mount("#app");
    #app { line-height: 1.75; }
    [v-cloak] { display: none; }
    .comment { color: #A0A0A0}
    <link href="https://unpkg.com/primevue/resources/themes/lara-light-indigo/theme.css" rel="stylesheet">
    <link href="https://unpkg.com/primevue/resources/primevue.min.css" rel="stylesheet">
    <link href="https://unpkg.com/primeicons/primeicons.css" rel="stylesheet">
    <div id="app">
    displayModal: {{displayModal}}<br/>
     <p-button
        class="datatable-button"
        icon="pi pi-pencil"
        label="XXX"
        @click="openModal"
      ></p-button>
      <modal-dialog :visible="displayModal" @update:visible="closeDialog($event)" />    
    </div>
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
    <script src="https://unpkg.com/primevue/core/core.min.js"></script>
    <script src="https://unpkg.com/primevue/button/button.min.js"></script>
    <script type="text/x-template" id="modal-dialog">
    <p-dialog
        header="###"
        v-model:visible="visible"
        :breakpoints="{ '960px': '75vw', '640px': '90vw' }"
        :style="{ width: '50vw' }"    
      >                   
         <template #footer>
            <p-button
            label="Close"
            class="p-button p-button-secondary"
            icon="pi pi-times"
            @click="closeModal()"
          ></p-button>
          <p-button
            label="Guardar"
            class="p-button p-button-primary"
            icon="pi pi-check"
            autofocus
            v-model:visible="displayModal"
          ></p-button>
        </template>
      </p-dialog>
     </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search