Chris Chris - 4 months ago 92
Javascript Question

vuejs: v-if directive for event?

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>

Answer

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)
  }
}