How to call function on child component on parent eventsVUEJS 2: Events. Parent to trigger an method found in a child componentCommunication between sibling components in VueJs 2.0Event from parent to child componentCall child method using slotVue - On Click on Button (Parent), emit data from child-componentHow to manage a redirect request after a jQuery Ajax callPure JavaScript equivalent of jQuery's $.ready() - how to call a function when the page/DOM is ready for itHow do I return the response from an asynchronous call?Vue.js: Using prerendered html as template for parent and child componentsDelete a Vue child componentHow to catch events across multiple child Vue componentsVue.js: Disabling a button on parent component based on state of child componentListen to events from parent component in child and execute child’s method in vue without hubHow to properly pass data to sibling component using VueJS?Vue component wrapping
Plot irregular circle in latex
Does household ovens ventilate heat to the outdoors?
How often is duct tape used during crewed space missions?
Have you ever been issued a passport or national identity card for travel by any other country?
A Pixelated Sequence - Find the Continuation
Why is belonging not transitive?
Why does dd not make working bootable USB sticks for Microsoft?
Does Forgotten Realms setting count as “High magic”?
Which version of the Pigeonhole principle is correct? One is far stronger than the other
Why is the year in this ISO timestamp not 2019?
Why don't airports use arresting gears to recover energy from landing passenger planes?
Are there any “Third Order” acronyms used in space exploration?
Is it acceptable to use decoupling capacitor ground pad as ground for oscilloscope probe?
Why is the UK still pressing on with Brexit?
What does the Free Recovery sign (UK) actually mean?
Answer Not A Fool, or Answer A Fool?
Tips for remembering the order of parameters for ln?
Pure python range implementation
Why would short-haul flights be pressurised at a higher cabin pressure?
Where is it? - The Google Earth Challenge Ep. 4
Maximum-cardinality matching in unbalanced bipartite graphs
How to give my students a straightedge instead of a ruler
Why is it called a stateful and a stateless firewall?
Wouldn't Kreacher have been able to escape even without following an order?
How to call function on child component on parent events
VUEJS 2: Events. Parent to trigger an method found in a child componentCommunication between sibling components in VueJs 2.0Event from parent to child componentCall child method using slotVue - On Click on Button (Parent), emit data from child-componentHow to manage a redirect request after a jQuery Ajax callPure JavaScript equivalent of jQuery's $.ready() - how to call a function when the page/DOM is ready for itHow do I return the response from an asynchronous call?Vue.js: Using prerendered html as template for parent and child componentsDelete a Vue child componentHow to catch events across multiple child Vue componentsVue.js: Disabling a button on parent component based on state of child componentListen to events from parent component in child and execute child’s method in vue without hubHow to properly pass data to sibling component using VueJS?Vue component wrapping
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Context
In Vue 2.0 the documentation and others clearly indicate that communication from parent to child happens via props.
Question
How does a parent tell its child an event has happened via props?
Should I just watch a prop called event? That doesn't feel right, nor do alternatives ($emit
/$on
is for child to parent, and a hub model is for distant elements).
Example
I have a parent container and it needs to tell its child container that it's okay to engage certain actions on an API. I need to be able to trigger functions.
javascript vue.js event-handling vuejs2
add a comment
|
Context
In Vue 2.0 the documentation and others clearly indicate that communication from parent to child happens via props.
Question
How does a parent tell its child an event has happened via props?
Should I just watch a prop called event? That doesn't feel right, nor do alternatives ($emit
/$on
is for child to parent, and a hub model is for distant elements).
Example
I have a parent container and it needs to tell its child container that it's okay to engage certain actions on an API. I need to be able to trigger functions.
javascript vue.js event-handling vuejs2
add a comment
|
Context
In Vue 2.0 the documentation and others clearly indicate that communication from parent to child happens via props.
Question
How does a parent tell its child an event has happened via props?
Should I just watch a prop called event? That doesn't feel right, nor do alternatives ($emit
/$on
is for child to parent, and a hub model is for distant elements).
Example
I have a parent container and it needs to tell its child container that it's okay to engage certain actions on an API. I need to be able to trigger functions.
javascript vue.js event-handling vuejs2
Context
In Vue 2.0 the documentation and others clearly indicate that communication from parent to child happens via props.
Question
How does a parent tell its child an event has happened via props?
Should I just watch a prop called event? That doesn't feel right, nor do alternatives ($emit
/$on
is for child to parent, and a hub model is for distant elements).
Example
I have a parent container and it needs to tell its child container that it's okay to engage certain actions on an API. I need to be able to trigger functions.
javascript vue.js event-handling vuejs2
javascript vue.js event-handling vuejs2
edited Apr 5 '18 at 18:57
Emile Bergeron
11.5k4 gold badges48 silver badges80 bronze badges
11.5k4 gold badges48 silver badges80 bronze badges
asked Mar 6 '17 at 18:14
jbodilyjbodily
6902 gold badges6 silver badges14 bronze badges
6902 gold badges6 silver badges14 bronze badges
add a comment
|
add a comment
|
9 Answers
9
active
oldest
votes
Give the child component a ref
and use $refs
to call a method on the child component directly.
html:
<div id="app">
<child-component ref="childComponent"></child-component>
<button @click="click">Click</button>
</div>
javascript:
var ChildComponent =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
new Vue(
el: '#app',
components:
'child-component': ChildComponent
,
methods:
click: function()
this.$refs.childComponent.setValue(2.0);
)
For more info, see Vue documentation on refs.
7
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
3
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
newbie question: Why useref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is usingref
even safe? Thanks
– Irfandy Jip
Jan 21 at 7:18
@IrfandyJip - yes,ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using aref
is totally fine, and it's not going to crash or anything.
– joerick
Feb 6 at 9:58
|
show 2 more comments
What you are describing is a change of state in the parent. You pass that to the child via a prop. As you suggested, you would watch
that prop. When the child takes action, it notifies the parent via an emit
, and the parent might then change the state again.
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
If you truly want to pass events to a child, you can do that by creating a bus (which is just a Vue instance) and passing it to the child as a prop.
2
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthandv-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.
– Falco
Oct 9 '17 at 15:16
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
4
It is very uncomfortable, you have to create an extraprop
in a child, an extra property indata
, then addwatch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.
– Илья Зеленько
Oct 31 '18 at 16:02
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
add a comment
|
You can use $emit
and $on
. Using @RoyJ code:
html:
<div id="app">
<my-component></my-component>
<button @click="click">Click</button>
</div>
javascript:
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
,
created: function()
this.$parent.$on('update', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
click: function()
this.$emit('update', 7);
)
Running example: https://jsfiddle.net/rjurado/m2spy60r/1/
4
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
2
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
9
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
5
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
1
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
|
show 1 more comment
If you have time, use Vuex store for watching variables (aka state) or trigger (aka dispatch) an action directly.
2
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
add a comment
|
Did not like the event-bus approach using $on
bindings in the child during create
. Why? Subsequent create
calls (I'm using vue-router
) bind the message handler more than once--leading to multiple responses per message.
The orthodox solution of passing props down from parent to child and putting a property watcher in the child worked a little better. Only problem being that the child can only act on a value transition. Passing the same message multiple times needs some kind of bookkeeping to force a transition so the child can pick up the change.
I've found that if I wrap the message in an array, it will always trigger the child watcher--even if the value remains the same.
Parent:
data: function()
msgChild: null,
,
methods:
mMessageDoIt: function()
this.msgChild = ['doIt'];
...
Child:
props: ['msgChild'],
watch:
'msgChild': function(arMsg)
console.log(arMsg[0]);
HTML:
<parent>
<child v-bind=" 'msgChild': msgChild "></child>
</parent>
1
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
1
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
1
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
add a comment
|
A simple decoupled way to call methods on child components is by emitting a handler from the child and then invoking it from parent.
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
The parent keeps track of the child handler functions and calls whenever necessary.
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
add a comment
|
The below example is self explainatory. where refs and events can be used to call function from and to parent and child.
// PARENT
<template>
<parent>
<child
@onChange="childCallBack"
ref="childRef"
:data="moduleData"
/>
<button @click="callChild">Call Method in child</button>
</parent>
</template>
<script>
export default
methods:
callChild()
this.$refs.childRef.childMethod('Hi from parent');
,
childCallBack(message)
console.log('message from child', message);
;
</script>
// CHILD
<template>
<child>
<button @click="callParent">Call Parent</button>
</child>
</template>
<script>
export default
methods:
callParent()
this.$emit('onChange', 'hi from child');
,
childMethod(message)
console.log('message from parent', message);
</script>
add a comment
|
I think we should to have a consideration about the necessity of parent to use the child’s methods.In fact,parents needn’t to concern the method of child,but can treat the child component as a FSA(finite state machine).Parents component to control the state of child component.So the solution to watch the status change or just use the compute function is enough
add a comment
|
You could use a mixin to set a shared data attribute. Change it in the parent, watch it in the child:
// mixin
export default
data()
return
clicked: false
// parent
export default
mixins: [myMixin],
methods:
btnClick()
this.clicked = true
// child
export default
mixins: [myMixin],
watch:
clicked(val)
if(val)
// yay
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42632711%2fhow-to-call-function-on-child-component-on-parent-events%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
9 Answers
9
active
oldest
votes
9 Answers
9
active
oldest
votes
active
oldest
votes
active
oldest
votes
Give the child component a ref
and use $refs
to call a method on the child component directly.
html:
<div id="app">
<child-component ref="childComponent"></child-component>
<button @click="click">Click</button>
</div>
javascript:
var ChildComponent =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
new Vue(
el: '#app',
components:
'child-component': ChildComponent
,
methods:
click: function()
this.$refs.childComponent.setValue(2.0);
)
For more info, see Vue documentation on refs.
7
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
3
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
newbie question: Why useref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is usingref
even safe? Thanks
– Irfandy Jip
Jan 21 at 7:18
@IrfandyJip - yes,ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using aref
is totally fine, and it's not going to crash or anything.
– joerick
Feb 6 at 9:58
|
show 2 more comments
Give the child component a ref
and use $refs
to call a method on the child component directly.
html:
<div id="app">
<child-component ref="childComponent"></child-component>
<button @click="click">Click</button>
</div>
javascript:
var ChildComponent =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
new Vue(
el: '#app',
components:
'child-component': ChildComponent
,
methods:
click: function()
this.$refs.childComponent.setValue(2.0);
)
For more info, see Vue documentation on refs.
7
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
3
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
newbie question: Why useref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is usingref
even safe? Thanks
– Irfandy Jip
Jan 21 at 7:18
@IrfandyJip - yes,ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using aref
is totally fine, and it's not going to crash or anything.
– joerick
Feb 6 at 9:58
|
show 2 more comments
Give the child component a ref
and use $refs
to call a method on the child component directly.
html:
<div id="app">
<child-component ref="childComponent"></child-component>
<button @click="click">Click</button>
</div>
javascript:
var ChildComponent =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
new Vue(
el: '#app',
components:
'child-component': ChildComponent
,
methods:
click: function()
this.$refs.childComponent.setValue(2.0);
)
For more info, see Vue documentation on refs.
Give the child component a ref
and use $refs
to call a method on the child component directly.
html:
<div id="app">
<child-component ref="childComponent"></child-component>
<button @click="click">Click</button>
</div>
javascript:
var ChildComponent =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
new Vue(
el: '#app',
components:
'child-component': ChildComponent
,
methods:
click: function()
this.$refs.childComponent.setValue(2.0);
)
For more info, see Vue documentation on refs.
edited Feb 6 at 9:44
answered Aug 2 '17 at 14:25
joerickjoerick
12k3 gold badges45 silver badges53 bronze badges
12k3 gold badges45 silver badges53 bronze badges
7
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
3
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
newbie question: Why useref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is usingref
even safe? Thanks
– Irfandy Jip
Jan 21 at 7:18
@IrfandyJip - yes,ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using aref
is totally fine, and it's not going to crash or anything.
– joerick
Feb 6 at 9:58
|
show 2 more comments
7
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
3
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
newbie question: Why useref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is usingref
even safe? Thanks
– Irfandy Jip
Jan 21 at 7:18
@IrfandyJip - yes,ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using aref
is totally fine, and it's not going to crash or anything.
– joerick
Feb 6 at 9:58
7
7
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
This way parent and child components become coupled. For real events, say when you can't just change a prop to trigger an action, I would go with the bus solution suggested by @Roy J
– Jared
Apr 19 '18 at 17:12
3
3
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
a ref to the docs would be a helpful aswell vuejs.org/v2/guide/…
– ctf0
Aug 21 '18 at 1:22
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
In my child component, for special reasons, I had to use v-once to terminate the reactivity. Thus passing the prop down from parent to child wasn't an option, so this solution did the trick!
– John
Sep 15 '18 at 3:12
newbie question: Why use
ref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is using ref
even safe? Thanks– Irfandy Jip
Jan 21 at 7:18
newbie question: Why use
ref
instead of creating a prop, that watches its value then emit it to another function in parent? I mean it does has a lot of things to do, but is using ref
even safe? Thanks– Irfandy Jip
Jan 21 at 7:18
@IrfandyJip - yes,
ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using a ref
is totally fine, and it's not going to crash or anything.– joerick
Feb 6 at 9:58
@IrfandyJip - yes,
ref
is safe. Generally, it's discouraged because the Vue community prefers to pass state to children, and events back to the parent. Generally speaking, this leads to more isolated, internally-consistent components (a good thing™). But, if the information you're passing to the child really is an event (or a command), modifying state isn't the right pattern. In that case, calling a method using a ref
is totally fine, and it's not going to crash or anything.– joerick
Feb 6 at 9:58
|
show 2 more comments
What you are describing is a change of state in the parent. You pass that to the child via a prop. As you suggested, you would watch
that prop. When the child takes action, it notifies the parent via an emit
, and the parent might then change the state again.
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
If you truly want to pass events to a child, you can do that by creating a bus (which is just a Vue instance) and passing it to the child as a prop.
2
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthandv-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.
– Falco
Oct 9 '17 at 15:16
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
4
It is very uncomfortable, you have to create an extraprop
in a child, an extra property indata
, then addwatch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.
– Илья Зеленько
Oct 31 '18 at 16:02
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
add a comment
|
What you are describing is a change of state in the parent. You pass that to the child via a prop. As you suggested, you would watch
that prop. When the child takes action, it notifies the parent via an emit
, and the parent might then change the state again.
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
If you truly want to pass events to a child, you can do that by creating a bus (which is just a Vue instance) and passing it to the child as a prop.
2
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthandv-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.
– Falco
Oct 9 '17 at 15:16
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
4
It is very uncomfortable, you have to create an extraprop
in a child, an extra property indata
, then addwatch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.
– Илья Зеленько
Oct 31 '18 at 16:02
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
add a comment
|
What you are describing is a change of state in the parent. You pass that to the child via a prop. As you suggested, you would watch
that prop. When the child takes action, it notifies the parent via an emit
, and the parent might then change the state again.
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
If you truly want to pass events to a child, you can do that by creating a bus (which is just a Vue instance) and passing it to the child as a prop.
What you are describing is a change of state in the parent. You pass that to the child via a prop. As you suggested, you would watch
that prop. When the child takes action, it notifies the parent via an emit
, and the parent might then change the state again.
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
If you truly want to pass events to a child, you can do that by creating a bus (which is just a Vue instance) and passing it to the child as a prop.
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
var Child =
template: '<div>counter</div>',
props: ['canI'],
data: function ()
return
counter: 0
;
,
watch:
canI: function ()
if (this.canI)
++this.counter;
this.$emit('increment');
new Vue(
el: '#app',
components:
'my-component': Child
,
data:
childState: false
,
methods:
permitChild: function ()
this.childState = true;
,
lockChild: function ()
this.childState = false;
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="app">
<my-component :can-I="childState" v-on:increment="lockChild"></my-component>
<button @click="permitChild">Go</button>
</div>
edited Nov 19 '17 at 15:14
answered Mar 6 '17 at 19:27
Roy JRoy J
30.4k5 gold badges37 silver badges64 bronze badges
30.4k5 gold badges37 silver badges64 bronze badges
2
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthandv-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.
– Falco
Oct 9 '17 at 15:16
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
4
It is very uncomfortable, you have to create an extraprop
in a child, an extra property indata
, then addwatch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.
– Илья Зеленько
Oct 31 '18 at 16:02
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
add a comment
|
2
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthandv-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.
– Falco
Oct 9 '17 at 15:16
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
4
It is very uncomfortable, you have to create an extraprop
in a child, an extra property indata
, then addwatch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.
– Илья Зеленько
Oct 31 '18 at 16:02
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
2
2
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthand
v-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.– Falco
Oct 9 '17 at 15:16
I think this is the only answer in line with the official Vue.JS style guide and best practices. If you use the shorthand
v-model
on the component, you can also easily reset the value by emitting the corresponding event with less code.– Falco
Oct 9 '17 at 15:16
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
For example, I want to give an alert when a user clicks a button. Do you propose for example: - watch a flag - set this flag from 0 to 1 when a click occurs, - do something - reset flag
– Sinan Erdem
Nov 23 '17 at 14:34
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
I would not expect the child to raise an alert for a click in the parent, but if that is what you wanted to do, I would pass a bus to the child and have the parent emit on the bus.
– Roy J
Nov 23 '17 at 18:22
4
4
It is very uncomfortable, you have to create an extra
prop
in a child, an extra property in data
, then add watch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.– Илья Зеленько
Oct 31 '18 at 16:02
It is very uncomfortable, you have to create an extra
prop
in a child, an extra property in data
, then add watch
... It would be comfortable if there was built-in support to somehow transfer events from parent to child. This situation occurs quite often.– Илья Зеленько
Oct 31 '18 at 16:02
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
As state by @ИльяЗеленько, it does happen quite often, it would be a godsend right about now.
– Craig
Jul 8 at 20:28
add a comment
|
You can use $emit
and $on
. Using @RoyJ code:
html:
<div id="app">
<my-component></my-component>
<button @click="click">Click</button>
</div>
javascript:
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
,
created: function()
this.$parent.$on('update', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
click: function()
this.$emit('update', 7);
)
Running example: https://jsfiddle.net/rjurado/m2spy60r/1/
4
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
2
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
9
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
5
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
1
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
|
show 1 more comment
You can use $emit
and $on
. Using @RoyJ code:
html:
<div id="app">
<my-component></my-component>
<button @click="click">Click</button>
</div>
javascript:
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
,
created: function()
this.$parent.$on('update', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
click: function()
this.$emit('update', 7);
)
Running example: https://jsfiddle.net/rjurado/m2spy60r/1/
4
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
2
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
9
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
5
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
1
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
|
show 1 more comment
You can use $emit
and $on
. Using @RoyJ code:
html:
<div id="app">
<my-component></my-component>
<button @click="click">Click</button>
</div>
javascript:
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
,
created: function()
this.$parent.$on('update', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
click: function()
this.$emit('update', 7);
)
Running example: https://jsfiddle.net/rjurado/m2spy60r/1/
You can use $emit
and $on
. Using @RoyJ code:
html:
<div id="app">
<my-component></my-component>
<button @click="click">Click</button>
</div>
javascript:
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue: function(value)
this.value = value;
,
created: function()
this.$parent.$on('update', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
click: function()
this.$emit('update', 7);
)
Running example: https://jsfiddle.net/rjurado/m2spy60r/1/
edited Mar 6 '17 at 20:28
answered Mar 6 '17 at 20:23
drinordrinor
3,4502 gold badges25 silver badges36 bronze badges
3,4502 gold badges25 silver badges36 bronze badges
4
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
2
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
9
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
5
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
1
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
|
show 1 more comment
4
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
2
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
9
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
5
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
1
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
4
4
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
I'm surprised it works. I thought emitting to a child was an anti-pattern, or that the intent was for emit to only be from child to parent. Are there any potential problems with going the other way?
– jbodily
Mar 6 '17 at 20:44
2
2
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
This may not be considered the best way, I don't know, but If you know what are you doing I thing threre is not a problem. The other way is use central bus: vuejs.org/v2/guide/…
– drinor
Mar 7 '17 at 7:24
9
9
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
This creates a coupling between the child and parent and is considered bad practice
– morrislaptop
Sep 12 '17 at 16:14
5
5
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
This only works because the parent is not a component but actually a vue app. In reality this is using the vue instance as a bus.
– Julio Rodrigues
Sep 14 '17 at 14:57
1
1
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
@Bsienn the call to this.$parent makes this component dependent on the parent. uses $emit to and props so the only dependencies are through Vue's communication system. This approach allows the same component to be used anywhere in the component hierarchy.
– morrislaptop
Jul 27 at 2:59
|
show 1 more comment
If you have time, use Vuex store for watching variables (aka state) or trigger (aka dispatch) an action directly.
2
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
add a comment
|
If you have time, use Vuex store for watching variables (aka state) or trigger (aka dispatch) an action directly.
2
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
add a comment
|
If you have time, use Vuex store for watching variables (aka state) or trigger (aka dispatch) an action directly.
If you have time, use Vuex store for watching variables (aka state) or trigger (aka dispatch) an action directly.
answered Sep 25 '17 at 14:23
brightknight08brightknight08
1011 silver badge4 bronze badges
1011 silver badge4 bronze badges
2
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
add a comment
|
2
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
2
2
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
due to reactivity of vuejs/vuex that is the best aproach, in parent make a action/mutation that change a vuex property value and in child have a computed value that get this same vuex $store.state.property.value or a "watch" method that do something when vuex "$store.state.property.value" changes
– FabianSilva
Dec 7 '17 at 15:21
add a comment
|
Did not like the event-bus approach using $on
bindings in the child during create
. Why? Subsequent create
calls (I'm using vue-router
) bind the message handler more than once--leading to multiple responses per message.
The orthodox solution of passing props down from parent to child and putting a property watcher in the child worked a little better. Only problem being that the child can only act on a value transition. Passing the same message multiple times needs some kind of bookkeeping to force a transition so the child can pick up the change.
I've found that if I wrap the message in an array, it will always trigger the child watcher--even if the value remains the same.
Parent:
data: function()
msgChild: null,
,
methods:
mMessageDoIt: function()
this.msgChild = ['doIt'];
...
Child:
props: ['msgChild'],
watch:
'msgChild': function(arMsg)
console.log(arMsg[0]);
HTML:
<parent>
<child v-bind=" 'msgChild': msgChild "></child>
</parent>
1
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
1
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
1
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
add a comment
|
Did not like the event-bus approach using $on
bindings in the child during create
. Why? Subsequent create
calls (I'm using vue-router
) bind the message handler more than once--leading to multiple responses per message.
The orthodox solution of passing props down from parent to child and putting a property watcher in the child worked a little better. Only problem being that the child can only act on a value transition. Passing the same message multiple times needs some kind of bookkeeping to force a transition so the child can pick up the change.
I've found that if I wrap the message in an array, it will always trigger the child watcher--even if the value remains the same.
Parent:
data: function()
msgChild: null,
,
methods:
mMessageDoIt: function()
this.msgChild = ['doIt'];
...
Child:
props: ['msgChild'],
watch:
'msgChild': function(arMsg)
console.log(arMsg[0]);
HTML:
<parent>
<child v-bind=" 'msgChild': msgChild "></child>
</parent>
1
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
1
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
1
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
add a comment
|
Did not like the event-bus approach using $on
bindings in the child during create
. Why? Subsequent create
calls (I'm using vue-router
) bind the message handler more than once--leading to multiple responses per message.
The orthodox solution of passing props down from parent to child and putting a property watcher in the child worked a little better. Only problem being that the child can only act on a value transition. Passing the same message multiple times needs some kind of bookkeeping to force a transition so the child can pick up the change.
I've found that if I wrap the message in an array, it will always trigger the child watcher--even if the value remains the same.
Parent:
data: function()
msgChild: null,
,
methods:
mMessageDoIt: function()
this.msgChild = ['doIt'];
...
Child:
props: ['msgChild'],
watch:
'msgChild': function(arMsg)
console.log(arMsg[0]);
HTML:
<parent>
<child v-bind=" 'msgChild': msgChild "></child>
</parent>
Did not like the event-bus approach using $on
bindings in the child during create
. Why? Subsequent create
calls (I'm using vue-router
) bind the message handler more than once--leading to multiple responses per message.
The orthodox solution of passing props down from parent to child and putting a property watcher in the child worked a little better. Only problem being that the child can only act on a value transition. Passing the same message multiple times needs some kind of bookkeeping to force a transition so the child can pick up the change.
I've found that if I wrap the message in an array, it will always trigger the child watcher--even if the value remains the same.
Parent:
data: function()
msgChild: null,
,
methods:
mMessageDoIt: function()
this.msgChild = ['doIt'];
...
Child:
props: ['msgChild'],
watch:
'msgChild': function(arMsg)
console.log(arMsg[0]);
HTML:
<parent>
<child v-bind=" 'msgChild': msgChild "></child>
</parent>
edited Mar 5 '18 at 6:34
answered Mar 5 '18 at 6:29
Jason StewartJason Stewart
1074 bronze badges
1074 bronze badges
1
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
1
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
1
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
add a comment
|
1
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
1
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
1
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
1
1
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
I think this won't work if msgChild has always the same status on the parent. For example: I want a component that opens a modal. The parent doesn't care if the current status is open or close, it just wants to open the modal at any moment. So, if the parent does this.msgChild = true; the modal is closed, and then the parent does this.msgChild = true, the child won't receive the event
– Jorge Sainz
Nov 19 '18 at 10:34
1
1
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
@JorgeSainz: That is why I'm wrapping the value in an array prior to assigning it to the data item. Without wrapping the value in an array, it behaves just as you specify. So, msgChild = true, msgChild = true -- no event. msgChild = [true], msgChild = [true] -- event!
– Jason Stewart
Nov 20 '18 at 11:20
1
1
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
I didn't see it. Thanks for the clarification
– Jorge Sainz
Nov 20 '18 at 14:01
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
This is cool, but feels a little hackish. I'm going to use it since it's the cleaner than using the component ref hack and less complicated that the event bus solution. I know that vue wants decoupling and only allow state changes to effect the component but there should be some builtin way to call a child's methods if needed. Perhaps a modifier on a prop that once it changes state you could automatically reset it to a default value so that the watcher is ready for the next state change. Anyway thanks for posting your find.
– Craig
Jul 5 at 15:51
add a comment
|
A simple decoupled way to call methods on child components is by emitting a handler from the child and then invoking it from parent.
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
The parent keeps track of the child handler functions and calls whenever necessary.
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
add a comment
|
A simple decoupled way to call methods on child components is by emitting a handler from the child and then invoking it from parent.
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
The parent keeps track of the child handler functions and calls whenever necessary.
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
add a comment
|
A simple decoupled way to call methods on child components is by emitting a handler from the child and then invoking it from parent.
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
The parent keeps track of the child handler functions and calls whenever necessary.
A simple decoupled way to call methods on child components is by emitting a handler from the child and then invoking it from parent.
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
The parent keeps track of the child handler functions and calls whenever necessary.
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
var Child =
template: '<div>value</div>',
data: function ()
return
value: 0
;
,
methods:
setValue(value)
this.value = value;
,
created()
this.$emit('handler', this.setValue);
new Vue(
el: '#app',
components:
'my-component': Child
,
methods:
setValueHandler(fn)
this.setter = fn
,
click()
this.setter(70)
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
<my-component @handler="setValueHandler"></my-component>
<button @click="click">Click</button>
</div>
answered Oct 30 '18 at 8:12
nilobarpnilobarp
2,2212 gold badges14 silver badges23 bronze badges
2,2212 gold badges14 silver badges23 bronze badges
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
add a comment
|
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
I like where this solution is going but what exactly is "this.setter" in the parent?
– Craig
Jul 5 at 15:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
It’s the setValue function reference emitted by the child component as an argument to handler event.
– nilobarp
Jul 7 at 16:16
add a comment
|
The below example is self explainatory. where refs and events can be used to call function from and to parent and child.
// PARENT
<template>
<parent>
<child
@onChange="childCallBack"
ref="childRef"
:data="moduleData"
/>
<button @click="callChild">Call Method in child</button>
</parent>
</template>
<script>
export default
methods:
callChild()
this.$refs.childRef.childMethod('Hi from parent');
,
childCallBack(message)
console.log('message from child', message);
;
</script>
// CHILD
<template>
<child>
<button @click="callParent">Call Parent</button>
</child>
</template>
<script>
export default
methods:
callParent()
this.$emit('onChange', 'hi from child');
,
childMethod(message)
console.log('message from parent', message);
</script>
add a comment
|
The below example is self explainatory. where refs and events can be used to call function from and to parent and child.
// PARENT
<template>
<parent>
<child
@onChange="childCallBack"
ref="childRef"
:data="moduleData"
/>
<button @click="callChild">Call Method in child</button>
</parent>
</template>
<script>
export default
methods:
callChild()
this.$refs.childRef.childMethod('Hi from parent');
,
childCallBack(message)
console.log('message from child', message);
;
</script>
// CHILD
<template>
<child>
<button @click="callParent">Call Parent</button>
</child>
</template>
<script>
export default
methods:
callParent()
this.$emit('onChange', 'hi from child');
,
childMethod(message)
console.log('message from parent', message);
</script>
add a comment
|
The below example is self explainatory. where refs and events can be used to call function from and to parent and child.
// PARENT
<template>
<parent>
<child
@onChange="childCallBack"
ref="childRef"
:data="moduleData"
/>
<button @click="callChild">Call Method in child</button>
</parent>
</template>
<script>
export default
methods:
callChild()
this.$refs.childRef.childMethod('Hi from parent');
,
childCallBack(message)
console.log('message from child', message);
;
</script>
// CHILD
<template>
<child>
<button @click="callParent">Call Parent</button>
</child>
</template>
<script>
export default
methods:
callParent()
this.$emit('onChange', 'hi from child');
,
childMethod(message)
console.log('message from parent', message);
</script>
The below example is self explainatory. where refs and events can be used to call function from and to parent and child.
// PARENT
<template>
<parent>
<child
@onChange="childCallBack"
ref="childRef"
:data="moduleData"
/>
<button @click="callChild">Call Method in child</button>
</parent>
</template>
<script>
export default
methods:
callChild()
this.$refs.childRef.childMethod('Hi from parent');
,
childCallBack(message)
console.log('message from child', message);
;
</script>
// CHILD
<template>
<child>
<button @click="callParent">Call Parent</button>
</child>
</template>
<script>
export default
methods:
callParent()
this.$emit('onChange', 'hi from child');
,
childMethod(message)
console.log('message from parent', message);
</script>
answered Oct 30 '18 at 8:35
MukundhanMukundhan
1,1987 silver badges20 bronze badges
1,1987 silver badges20 bronze badges
add a comment
|
add a comment
|
I think we should to have a consideration about the necessity of parent to use the child’s methods.In fact,parents needn’t to concern the method of child,but can treat the child component as a FSA(finite state machine).Parents component to control the state of child component.So the solution to watch the status change or just use the compute function is enough
add a comment
|
I think we should to have a consideration about the necessity of parent to use the child’s methods.In fact,parents needn’t to concern the method of child,but can treat the child component as a FSA(finite state machine).Parents component to control the state of child component.So the solution to watch the status change or just use the compute function is enough
add a comment
|
I think we should to have a consideration about the necessity of parent to use the child’s methods.In fact,parents needn’t to concern the method of child,but can treat the child component as a FSA(finite state machine).Parents component to control the state of child component.So the solution to watch the status change or just use the compute function is enough
I think we should to have a consideration about the necessity of parent to use the child’s methods.In fact,parents needn’t to concern the method of child,but can treat the child component as a FSA(finite state machine).Parents component to control the state of child component.So the solution to watch the status change or just use the compute function is enough
answered Jul 26 '18 at 13:57
user10097040user10097040
293 bronze badges
293 bronze badges
add a comment
|
add a comment
|
You could use a mixin to set a shared data attribute. Change it in the parent, watch it in the child:
// mixin
export default
data()
return
clicked: false
// parent
export default
mixins: [myMixin],
methods:
btnClick()
this.clicked = true
// child
export default
mixins: [myMixin],
watch:
clicked(val)
if(val)
// yay
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
add a comment
|
You could use a mixin to set a shared data attribute. Change it in the parent, watch it in the child:
// mixin
export default
data()
return
clicked: false
// parent
export default
mixins: [myMixin],
methods:
btnClick()
this.clicked = true
// child
export default
mixins: [myMixin],
watch:
clicked(val)
if(val)
// yay
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
add a comment
|
You could use a mixin to set a shared data attribute. Change it in the parent, watch it in the child:
// mixin
export default
data()
return
clicked: false
// parent
export default
mixins: [myMixin],
methods:
btnClick()
this.clicked = true
// child
export default
mixins: [myMixin],
watch:
clicked(val)
if(val)
// yay
You could use a mixin to set a shared data attribute. Change it in the parent, watch it in the child:
// mixin
export default
data()
return
clicked: false
// parent
export default
mixins: [myMixin],
methods:
btnClick()
this.clicked = true
// child
export default
mixins: [myMixin],
watch:
clicked(val)
if(val)
// yay
answered Mar 28 at 12:58
digoutdigout
92711 silver badges20 bronze badges
92711 silver badges20 bronze badges
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
add a comment
|
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
Why will they share data attribute? The components should have separate contexts for attribute, shouldn't they?
– rinatdobr
Jun 21 at 6:37
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42632711%2fhow-to-call-function-on-child-component-on-parent-events%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown