Is it possible to emit from mounted in Vuejs? - vue.js

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
}

Related

Vue 3 - Prevent event propagation on custom event handlers

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

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 to observer child vue finish render

I am working on a chat tool using vue single file components.I am facing a problem,root .vue has child .vue and grandchild .vue, I want to observer children's rendering,to get the root div's height,to change scrollbar position,
i used the $nextTick() http://rc.vuejs.org/api/#vm-nextTick,but it cant observer children's render,so ,is there any way can I try? thanks a lot.
You can use parent child communication of vue to get to know when you child has rendered. Vue provided following event interface:
Listen to an event using $on(eventName)
Trigger an event using
$emit(eventName)
A parent component can listen to the events emitted from a child component using v-on directly in the template where the child component is used.
So you can emit a event in your child component's lifecycle hook like following:
mounted () {
this.$emit('childRendered')
}
In parent component, you can listen to this event or create a method, like following:
this.$on('childRendered', function () {
// change scrollbar position
})
An example of parent child communication: fiddle
This is just for everyone to easily see the workaround that was mentioned by Saurabh in his comment to his answer. I also used the updated lifecycle to wait for the DOM to finish rendering and patching before manipulating it again.
Since updated does not guarantee that all child components have also been re-rendered, use vm.$nextTick inside of updated.
updated: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been re-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.

Broadcasting event from parent to child fires all parent's children in Vue.js

I have a parent component and a child component.
In my parent component I have an event on a span:
<span #click="toggle(model.id)" class="open-folder">[{{open ? '-' : '+'}}]</span>
which fires the toggle function
methods: {
toggle: function(id_epic) {
this.open = !this.open;
this.$broadcast('loadTasks', id_epic);
}
},
in this function I call the loadTasks method from the child component with id_epic parameter.
The parent can have n children linked to it, but I only want to fire the first child method not all.
When I click on the span it fires the event for all n children of the parent's tree.
EDIT: The parent and it's children are generated recursively, so the child can also be a parent on it's own.(Like a folder structure)
How can I fix this ?
Thank you.
$broadcast is used to send event to child components. In your parent component you're triggering the event loadTasks from the toggle method. This is good.
You're sending a parameter along in the event, in your case id_epic
Now in your child component, you will need something like this. You need to get the id you're sending in your child component.
events : {
'loadTask' : function(param) {
//check for the id_epic here
}
}
EDIT: The parent and it's children are generated recursively, so the child can also be a parent on it's own.(Like a folder structure)
You should also re-think that part, if you have too many nested components, things can get easily out of hand.
You should be able to stop the propagation of an event by using a second parameter in the child listener. The second parameter is passed the event object to which you can can call stopProgation() and prevent additional children from also receiving the broadcasted event.
Consider adding the following code to your child listener.
events:{
'loadTask': function(param,event){
event.stopPropagtion();
// Handle the param as needed.
}
}
Of course this system of event handling is only for Vue.js 1.0 as in Vue.js 2.0+ event broadcasting and dispatching has been depreciated in favor of a data store such as Vuex. So you may want to consider using a method which will upgrade compatible.
You can try using this.$children[0].$emit() to send the event to the first child instance. though it would probably be better to use a more explicit scheme and have children register handlers with the parent or vice versa.