vue-final / vue-final-modal

🍕Vue Final Modal is a tiny, renderless, mobile-friendly, feature-rich modal component for Vue.js.
https://vue-final-modal.org
MIT License
896 stars 97 forks source link

Dynamic modal that opens another dynamic modal, cannot pass the emit back to parent component #340

Closed yuejt14 closed 9 months ago

yuejt14 commented 1 year ago

Version

vue-final-modal: v3.4.11 vue: v3.2.45

OS

Mac

Steps to reproduce

I am trying to use use $vfm.show to open one modal, and inside that modal it opens another one. After confirmation, the last modal should emit an event to the first modal , and the second modal should emit the signal back to the parent component. The codes looks like this:

parent.vue

import one from "../modals/one.vue";
export default {
  name: "parent",
  methods: {
    openOne(){
      console.log("opening first modal");
      let that = this;
      that.$vfm.show({
        component: one,
        on: {
          confirm() {
            console.log("Home received confirm from one");
          }
        }
      });
    }
  }
}
</script>
<template>
  <div>
    <div>this is home</div>
    <button @click="openOne"> test </button>
  </div>
</template>

one.vue

  <vue-final-modal
      v-slot='{ close }'
      v-bind='$attrs'
      :hide-overlay="true"
      @opened="$emit('opened')"
      @closed="$emit('closed')">
    <div>hello this is number one</div>
    <button @click="openTwo(close)"> ONE</button>
    <slot />
  </vue-final-modal>
</template>

<script>
import two from "./two.vue";

export default {
  name: "one",
  methods: {
    openTwo(close){
      console.log("Opening two");
      const that = this;
      close();
      this.$vfm.show({
        component: two,
        on: {
          confirmTwo() {
            console.log("One received confirm from two");
            that.$emit("confirm");
          }
        }
      });
    }
  }
};
</script>

two.vue

  <vue-final-modal
      v-slot='{ close }'
      v-bind='$attrs'
      :hide-overlay="true"
      @opened="$emit('opened')"
      @closed="$emit('closed')">
    <div>hello this is number Two</div>
    <button @click="confirm(close)"> Two</button>
    <slot/>
  </vue-final-modal>
</template>

<script>
export default {
  name: "two",
  methods: {
    confirm (close) {
      close();
      console.log("Two is emitting confirm");
      this.$emit("confirmTwo");
    }
  }
};
</script>

What is Expected?

So everything works fine, except that when modal one received the event emitted from modal two, it doesn't seem to send the confirm back to parent, the onConfirm in parent.vue never get called. If i removes the "close()" in modal one, then the parent.vue will receive the confirm from modal, but then modal one will remains open when modal two is opened.

yuejt14 commented 1 year ago

So i found that Vue has an update that a component cannot emit after being unmounted, is there a way to maybe hide the modal without unmount the modal?

hunterliu1003 commented 9 months ago

@yuejt14 You have to use new Promise to wrap the second modal, when the second modal closed or emit a event, resolve the promise. In the first dynamic modal, you can put you logic after await or inside .then(() => {})