Replies: 7 comments
-
Note: If you define the event as a prop instead of an emit, you can do that today (onXXX props are what v-on:XXX is translated to by th compiler): <template>
<button v-on:click="handleClick">Post and Close</button>
</template>
<script>
export default {
props: ['onPost', 'onClose'],
methods: {
handleClick(a) {
this.onPost('post')
.then(res => res && this.onClose())
},
}
}
</script>
or a slightly more Usage in the parent would stay the same, as |
Beta Was this translation helpful? Give feedback.
-
@LinusBorg , thanks for your note. What I would like to add as feature is for |
Beta Was this translation helpful? Give feedback.
-
I understand. For now, you could write such an emit function yourself. Something like: app.config.globalProperties.$myEmit = function (prop, ...args) {
const prop = this.$props[prop]
if (!prop || typeof prop !== 'function') { return Promise.resolve(false) }
return Promise.resolve(prop(...args))
} Usage: <template>
<button v-on:click="handleClick">Post and Close</button>
</template>
<script>
export default {
props: ['onPost', 'onClose'],
methods: {
handleClick(a) {
this.$myEmit('onPost')
.then(res => res && this.$myEmit('onClose'))
},
}
}
</script> |
Beta Was this translation helpful? Give feedback.
-
Does this feature have any priority in vue 3? Since Vue's philosophy is "Props to pass down data, emits to pass up data", passing callback functions as props feel like an anti-pattern to me. It would be really great to be able to know if an emit was added to the component (such as |
Beta Was this translation helpful? Give feedback.
-
I have found a workaround; the pattern looks like this. @AyloSrd
|
Beta Was this translation helpful? Give feedback.
-
Probably best to manage this with the event argument. Something like: class AsyncEmitArgs {
#promises;
waitFor(p) {
this.#promises ??= [];
this.#promises.push(p);
}
get done() {
return this.#promises ? Promise.all(this.#promises) : true;
}
}
// In component:
const args = new AsyncEmitArgs();
emit(args);
await args.done;
// In listeners:
function onClick(args) {
const { promise, resolve } = Promise.withResolvers();
args.waitFor(promise);
setTimeout(resolve, 1000);
} |
Beta Was this translation helpful? Give feedback.
-
any updates? |
Beta Was this translation helpful? Give feedback.
-
What problem does this feature solve?
When working with Component Events emitted with
$emit
, we may need, once the callback function is executed, to chain another callback, or another Component Event. This is especially relevant when the event callback is an asynchronous one (e.g. an API call).As of now, we can achieve this only by notifying the child component via additional props, that the first callback has been executed, and then react to the notification with another callback; this requires though a lot of boilerplate code, and can result in a very complex props flow and inner logic.
It would be great if
$emit
retuned a Promise, that resolved totrue
when the callback has been executed, orfalse
in all the other cases: the callback is null or undefined, the event has a.once
modifier and was executed previously, an error is thrown, etc.It would allow to create components that are less dependent on their parents' input, to reduce the amount of boilerplate code, as well as the complexity coming from having to manage a more complex props flow, and to obtain a leaner inner logic. The "one source of truth" principle would remain unbreached, as the Promise is not returning the actual value of the callback, but only notifying its execution.
What does the proposed API look like?
In the child component, the easiest case scenario :
or a slightly more complex one :
and, in both cases the parent will have this:
Beta Was this translation helpful? Give feedback.
All reactions