2

Can I react to an event in a vue template? Say a child component dispatches an event $dispatch('userAdded'), could I do something like this in the parent component:

<div class="alert alert-info" v-if="userAdded"> User was created! </div> 

or, if not, can I access variables of the child component?

<div class="alert alert-info" v-if="$refs.addView.form.successful"> User was created! </div> 

I tried both without success.

Also, while I'm here, is there an expressive way to hide elements after a certain amount of time? Something like (to hide after 2s):

<div class="alert alert-info" v-if="$refs.addView.form.successful" hide-after="2000"> User was created! </div> 

Thanks!

edit: wrote my own hide-after directive:

Vue.directive('hide-after', { update: function(value) { setTimeout(() => this.el.remove(), value); } }); <div class="alert alert-info" v-hide-after="2000"> This will be shown for 2 seconds </div> 
7
  • is form.successful part of the data, props or a computed in your addView component? Commented Jul 25, 2016 at 7:59
  • why dont you just dispatch an event with the info from the child you need? Commented Jul 25, 2016 at 8:18
  • @nils: form.successful is part of my data in the addView component Commented Jul 25, 2016 at 8:43
  • @eltonkamami: and then write that info to the parent's data? That's what I'm trying to avoid if there's an easier way. Commented Jul 25, 2016 at 8:43
  • @Chris as i understand from your code, child handles creation and parent shows success message. you can pass a parent function as a prop to the child and call it upon user creation. either predefine the property to parents data or create it with this.$set on the fly Commented Jul 25, 2016 at 8:50

2 Answers 2

4

Yes you can but you need to take this approach.

  1. Create a child that dispatches an event
  2. In the parent component create an event listener for the event and also a data property that the event listener will set locally on the component instance
  3. In the parent bind your v-if to the local data component

The code would look something like

parent

HTML

<div v-if="showAlert"></div> 

Js

events: { 'alert.show': function () { this.showAlert = true }, 'alert.hide': function () { this.showAlert = false } }, data () { return { showAlert: false } } 

Child

Js

methods: { showAlert (show) { show ? this.$dispatch('alert.show') : this.$dispatch('alert.hide') } } 

The reason you should avoid using the $child and $parent is that it makes that component always depend on the fact that the parent will have the alert property and makes the child component lest modular

Since dispatch goes up until it hits a listener you can have several nested components in between the parent and child dispatching the alert control

UPDATE

Alternately, since you do not like the LOE of using events you can create a 2-way property on the child that either the parent or child can update

Example

Parent

HTML

<div v-if="showAlert"></div> <child-component :show-alert.sync="showAlert"></child-component> 

JS

data () { return { showAlert: false } } 

Child

js

props: { showAlert: { type: Boolean, twoWay: true } }, methods: { showAlertInParent (show) { this.$set('showAlert', show) } } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thought of that, was hoping there was a directer way. I'm accepting your answer anyway though :). Thanks for your reply.
@Chris - updated answer with an alternative using 2-way props
1

The whole idea of events is that you can react to them. But you want the reaction to pass by the model. You really don't want unrelated bits of markup listening and reacting 'independently'. $dispatch is deprecated. To do this now, do the following...

In the child component, emit an event as follows

this.$emit('didIt' {wasItAwful:'yep',wereYouScared:'absolutely'}); 

In the parent, you register the event listener with v-on, as an attribute of the child's tag...

<adventure-seeking-child v-on:did-it='myChildDidIt' /> 

Then, in the parent's methods, define your handler.

methods : { myChildDidIt : function(payload){ ... } } 

Docs are here.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.