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
})
}
Related
i have three vue.js file. where the parent file (parent.vue) contains data of profile:[]
the data of profile is send to child file (child.vue) using props methods.
the child.vue also has it's own child file (grandchild.vue) that has been pass with the profile data by using props.
grandchildren will send a put request to API to change some data in profile.
my question is. how can i make sure the props will update on every change made in the profile data.
information : (parent.vue = main file, child.vue = drawer(from ant design), grandchild = popover)
i need the child.vue to update the profile data after the grandchild succeed send a put request to the API.
is there any way or reference link so i could make the props update after a put request from grandchild.vue i have tried watch method but the problem is the user need to close the drawer (child.vue) first and re open the drawer to update the props. is there any way the props update without closing the drawer?
example of code :
parent.vue :
// structure
<child.vue
:profile="profile"
/>
child.vue & grandchild.vue :
//script
props : [profile],
profile can be used as {{profile.subsdata}} in html or this.profile.subsdata javascript
Use an emit. Tell the parent component to update via another GET request or just pass the data back directly.
Child Method:
notifyParent () {
this.$emit('updateProfile')
}
Parent Template:
<ChildComponent v-on:updateProfile="someMethod"/>
Parent Method:
someMethod () {
//GET request or whatever
}
More details here: https://v2.vuejs.org/v2/guide/components-custom-events.html
The keyword here is eventBus, you need an eventBus to $emit an event changing the data in the parent component from the grandchild component. If you only need to change up the data 1 layer instead of 2 in this case, you only need custom event + $emit, without the eventBus. But as it's greater than 2 layers, you need eventBus, or even more relegent ways to do state management.
I have a problem with accessing data from the component using slots.
Here's my code:
codepen.io/anon/pen/BbOEZz
I want the line:
<p slot="desc">{{ desc_01 }}</p>
It started working and at the slot in the template displayed the value with date.
Can anyone help me with this matter?
There are a couple of mistakes in your code
1.You don't access data directly from the child. The child communicates with the parent via events, using emit.
You should
fire an event from the child
listen to the event on the parent
update a variable on the parent.
2.There is no desc_01 declared on the app. The template is executed in the context of the app and not the child, so you also need to define that property.
data () {
return {
desc_01: ''
}
}
I've added a code pen for this here.
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
}
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.
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.