Vue 3 - Prevent event propagation on custom event handlers - vue.js

If i have a custom event handler like #my-event and i emit it with
this.$emit('my-event')
it calls all the events of #my-event from all parent components.
But i want to prevent this.
On normal event handlers like #click, we can simply add .stop behind it to prevent this behaviour.
But .stop does not work on custom event listeners.
Fiddle without stop: https://jsfiddle.net/xn9sq4cp/
Fiddle with stop: https://jsfiddle.net/xy18mspz/
I know i can add
inheritAttrs: false
to prevent event propagation globaly, but i dont want this.
So, how can i prevent event propagation for custom event handlers.
Thanks.

You can stop the component from emitting the event to stop it from being bubbled up by adding this:
// ...
emits: {
'my-event': false
}
// ...
JS Fiddle

Related

Vue leayk custom event being registered by multiple components

I have a custom event which is added via
...
mounted() {
window.addEventListener(...)
},
...
and am using event.stop.prevent but whereever I have those statements the events are registered, event when I do not want them to.
https://codesandbox.io/s/kw64lpk3y5
In the sandbox the event is defined in highlighter.vue
Highlighting a line of text should only add one sub array, but it is always registering 4...
So each component mounted adds an event to the "eventarray".
One possibility is to add this event to the component itself
or to filter by e.target
like so:
this.$el.addEventListener

How could the Vue app pass the additional parameters to the event listener when using vm.$once()?

In the Vue app , it could add the event listener that is called one time by using vm.$once.
For example, in the child component of Vue App, it could emit the event using vm.$emit('myEvent', data). emit event
And then it could be processed by adding the event listener to this event using vm.$once in the Vue app.
At this time, I want to pass the additional data to event handler.
I've tried as following. But it throws an error.
Uncaught ReferenceError: $event is not defined
//In the Vueapp
this.$refs.child.$once(
'myEvent', this.eventHandler($event, additional_data)
);
But I think that it could pass the additional data when using v-on.
<child-component ref="child" v-on:myEvent="eventHandler($event, additional_data)"></child-component>
//$event is the data emitted from the event , "myEvent".
When using vm.$once or vm.$on, couldn't it pass the additional parameter?
Note: the reason that I use vm.$once is that I want to execute the eventHandler only one time when emitting the custom event, myEvent and add it dynamically .
You need to capture the arguments passed into the event handler. You can do this by using an anonymous function for the handler that calls your method. For example
this.$refs.child.$once('myEvent', $event => {
this.eventHandler($event, additional_data)
})
You could also get fancy with Function.prototype.bind() however you would have to reverse the arguments list as bind prepends arguments.
For example
methods: {
eventHandler(data, $event) { // reversed argument list
// etc
}
}
and
this.$refs.child.$once('myEvent', this.eventHandler.bind(this, additional_data))

Is it possible to emit from mounted in Vuejs?

I am familiar with emitting data via bus on events and these work great but now I want to emit something but I don't have an event to tie it to.
I've tried to emit it on mounted but that hasn't worked as below:
mounted(){
bus.$emit('send-test', this.test);
},
When you add an event handler in the parent's mounted lifecycle event for an event that is emitted in a child's mounted event, the handler will not catch the event emitted by the child because the handler is added after the child has already emitted the event. Basically the cycle of events is like this.
Parent's create
Child's create
Child's mounted
Parent's mounted
Obviously there are other lifecycle events that occur, but that's the sequence that matters in this case.
If you want to handle an event emitted in the child, you need to create the handler (call $on) before the child's mounted event.
$nextTick may also be useful, it solved one of my issues and can be used like this
async mounted() {
await this.$nextTick()
// Code that will run only after the entire view has been rendered
}

Event custom event from main vue instance, listen from component

Pretty new to vue js here,
Just want to know if is it possible to emit a custom event from the main vue instance (parent) and the components could listen to that custom event and act accordingly when that event is triggered?
I want to trigger a custom event on vue instance mounted lifecycle function then all components can initialize themselves.
ex.
Main vue instance
new Vue( {
el : '#main-app',
mounted : function() {
this.$emit( 'init-app' );
}
} );
Then on the various components, it can listen for the 'init-app' custom event then act accordingly when it is triggered or emitted.
Not sure how to do this coz in vue js event listeners are attached to the html tags? can an event listener or a function in a component be triggered by just the emitting of the event from the parent alone?
Note: I'm using vue js 2.0.3
and my components are global, they are not inline
ex.
Vue.component('my-component', {
template: '#component-template'
});
I could add more components later on.
Thanks in advance.
The correct way to initialize your child components is to use created: life-cycle hook for each of your child components.
Reason: It is quite possible that your child component may not be instantiated when you send your init-app event from the parent component. So, it will never get initialized.
Additional note on events: If you are sending an event from child component to parent component, you should use this.$parent.$emit("my-event-code") and receive it on the parent side as this.$on("my-event-code"). I figured it out recently after hours of trying various methods.
So, if you are trying to send an init-app event from parent to child, you might have to listen on child component as this.$parent.$on("init-app", ...) - I haven't verified this yet, this is my current understanding.

Is there a "onExpand" event or similar for dijit.TitlePane?

Is there any way to get an event callback when the dojo-dijit's TitlePane expands?
I can capture onClick on the TitlePane. However, that is not enough for me. I have a button for "Expand All" TitlePanes. When user clicks on that I iterate on all TitlePanes and call it's toggle() method. When that happens, onClick event is not fired (as expected). I was wondering if there is any event fired upon toggle().
Or any other smart ways to address it also will be appreciated.
After looking into documentation in detail, I do not think there is any built in event that is fired during the toggle/expand. I ended up firing a custom event, and that helped me get what I wanted.
This answer helped me - https://stackoverflow.com/a/12852043/3810374
Basically,
First using isOpen() method, ensure the title pane is not already expanded. Then call toggle() method, and fire a custom event like this:
require(["dojo/on"], function(on){
// Send event
on.emit(target, "onExpand", {
bubbles: true,
cancelable: true
});
});
And then handle the event:
require(["dojo/on"], function(on){
// register event handler
on(target, "onExpand", function(e){
// handle event
});
});
You may be wondering, why not just do the work right after toggle(), instead of going through the pain of firing/handling event. I needed to handle the event in a particular closure, where I have access to other objects and variables.