vue-final-modal icon indicating copy to clipboard operation
vue-final-modal copied to clipboard

Closing the modal from withhin a slotted component on dynamic modals

Open Nekonyx13 opened this issue 3 years ago • 3 comments

I have this dynamic component, using a HOC and passing its content as its own component in the default slot. However, I want to be able to close the modal by clicking a button within the AddTask component. I am able to emit the "confirm" event, but this way I am unable to pass the close function to close the modal, so I need to use $vfm.hideAll() as a workaround.

this.$vfm.show({
        component: CustomModal,
        slots: {
          default: {
            component: AddTask,
            on: {
              confirm() {
                console.log("confirm");
                $vfm.hideAll();
              },
            },
          },
        },
      });

My question is: What would be the intended way to go about this?

Nekonyx13 avatar May 07 '22 21:05 Nekonyx13

Maybe this way: use v-slot="{ close }"?

CustomModal.vue

<template>
  <vue-final-modal v-slot="{ close }">
    <div class="modal__action">
      <slot @close="close"></slot>
     </div>
   </vue-final-mode>
</template>
...

AddTask.vue

<template>
  <base-modal>
    <template v-slot:action>
       <button @click="confirm(close)">ОК</button>
     </template>
</button>
<template>
...
<script>
export default {
  ...
 methods: {
    confirm(close) {
      this.$emit('add-task-confirm', close);
    },
...
}
</script>

and then call this.$vfm.show

this.$vfm.show({
        component: CustomModal,
        slots: {
          default: {
            component: AddTask,
            on: {
              addTaskConfirm(close) {
                console.log("confirm");
                close.onClose(); // !!!! another name of method
              },
            },
          },
        },
      });

drakoan avatar May 19 '22 11:05 drakoan

another way is using name of modal. Example:

onSomeEvent() {
  const modalName= 'myAwesomeModal';
  const $vfm = this.$vfm; // 'this' not defined on events like 'myAwesomeCmpConfirm'
  this.$vfm.show({
        component: BaseModal, // your modal with slot 'content' and props 'name' 
        bind: {
          'name': modalName,
        },
        slots: {
          'content': {
            component: MyAwesomeCmp, // your cmp with emits
            on: {
               myAwesomeCmpConfirm(succes) {
                if (succes) $vfm.hide(modalName); // or $vfm.hideAll(); if you need
              },
              myAwesomeCmpCancel() {
                $vfm.hide(modalName);
              },
            },
          },
        },
      });

drakoan avatar Jun 06 '22 17:06 drakoan

Borrowing the example from my PR here The approach is using symbol id that can be identified later and hide the modal by setting the value

import PopupInfo from './PopupInfo';

const modalId = Symbol('myModal')
$vfm.show({
  id: modalId,
  component: DummyModal,
  bind: {
    title: 'My Awesome Modal',
  },
  on: {
    closeTheModal: () => {
      const modal = getModalComponent(modalId) // getting the dynamic modal
      if (modal) {
        (modal as any).value = false // closing the specific dynamic modal
      }
    }
  }
});

const getModalComponent = (modalId: symbol): any | null => {
  let foundModal = null;
  for (const modal of $vfm.dynamicModals) {
    if (modal.id === modalId) {
      foundModal = modal;
      break;
    }
  }

  return foundModal;
};

PS: this example is using typescript, you may doing small adjustment for the JS version

slaveofcode avatar Sep 11 '22 09:09 slaveofcode

Please try to use name props to hide the dynamic modal

this.$vfm.show({
  component: CustomModal,
  bind: {
    name: 'UniqModalName'
  },
  slots: {
    default: {
      component: AddTask,
      on: {
        confirm() {
          console.log("confirm");
          $vfm.hide('UniqModalName');
        },
      },
    },
  },
});

hunterliu1003 avatar Oct 29 '22 18:10 hunterliu1003