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

[feature] A way to listen for custom events from programmatic modals

Open xaddict opened this issue 3 years ago • 7 comments

Problem:

I have a dynamic modal where the user can link two entities. Depending on what they do in the modal I would like to emit a custom event because in all cases I need to do something else in the parent component:

  • this.$emit('reload-list')
  • this.$emit('entities-unlinked')
  • this.$emit('oh-crap')

With a non-programmatic modal this is easy to do:

<CustomCom @reload-list="reloadStuff" />

the parent component has a method reloadStuff and the modal in CustomCom can then emit reload-list

however, with a programmatic modal:

this.$modal.show(CustomCom, props, params, events)

this event just gets shot into the ether and there's no real way to catch it.

So I would like a way to add this to events:

this.$modal.show(
  CustomCom,
  { ...props },
  { ...params },
  {
    'before-open': this.beforeOpen,
    'before-close': this.beforeClose
    'reload-list': this.reloadStuff
  }
)

Version:

1.3.35

I have checked stackoverflow for solutions and 100% sure that this issue is not not related to my code.

xaddict avatar Mar 12 '21 16:03 xaddict

You can pass functions as props. Here is how I'd do it:

Define the function to catch event from child component in parent

export default {
  name: 'ParentComp'
  methods: {
    catchChildEvent(eventFromChildComp) {
      console.log(eventFromChildComp)
    }
  }
}

Insert function as a prop in dynamic modal

this.$modal.show(
  ChildComp,
  {
     catchChildEvent: this.catchChildEvent
  },
  {
    name: 'ChildComp'
  },
  {
    'before-open': this.beforeOpen,
    'before-close': this.beforeClose
  }
)

Execute function in child component

<template>
  <div id="childComp">
    <a href="#" @click.prevent="eventOnChild('Hi, I came from child component!')" v-text="'click me!'" />
  </div>
</template>
export default {
  name: 'ChildComp',
  props: {
    catchChildEvent: {
      type: Function,
      default: () => {}
    }
  },
  methods: {
    eventOnChild(message) {
      this.catchChildEvent(message)
    }
  }
}

lvl99wzrd avatar Mar 22 '21 18:03 lvl99wzrd

It's a pretty clean workaround so I will try it.

But I would prefer just using plain emitters :)

xaddict avatar Mar 23 '21 08:03 xaddict

I would also like to use emitters, do you think that would be possible ?

amisora avatar Apr 20 '21 13:04 amisora

临时解决方案

let vm = this;
this.$modal.show(
 {
  extends: CustomCom,
  created(){
      this.$on('reload-list', vm.reloadStuff )
  }
},
  { ...props },
  { ...params },
  {
    'before-open': this.beforeOpen,
    'before-close': this.beforeClose
  }
)

soulmate126 avatar May 13 '21 09:05 soulmate126

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 26 '21 03:06 stale[bot]

@poulSoul global listeners will be deprecated in Vue 3.

Functions like described @marcoelissa don't have this problem. So I will use that for now.

xaddict avatar Jul 07 '21 13:07 xaddict

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 09 '22 07:01 stale[bot]