Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Composable functions for Vue event handlers

Tags:

vue.js

I'm using Vue 2.0, ES6, Webpack.

I have one component(let's call it Parent) and few children(let's call it text-input each). Every text-input emits an event called change and each one should alter one different property inside Parent. Let's say Parent has an data named info and inside info I have, name, email, etc.

What I want to accomplish is to set the right property(name, email, ...) using the same function for my @change option.

<text-input
   @change="alterProperty('name')">  
 </text-input>
 <text-input
   @change="alterProperty('email')">  
 </text-input>

My Parent would have this method:

alterProperty (property) {
  return (changeValue) => {
    this.info[property] = changeValue
  }
}

So far, nothing, I can't get this to work, maybe something in the way Vue handle things, I don't know. If anyone know something about that, I appreciate the help.

Thanks

like image 780
Cassio Cabral Avatar asked Oct 31 '16 05:10

Cassio Cabral


1 Answers

Please check this jsFiddle example: https://jsfiddle.net/mani04/2mmbsyy3/

It works precisely as you expect. Here is how I am using the text-input component:

<text-input :value="userInfo.name" @change="alterProperty('name', $event)"></text-input>

Note: alterProperty is an inline method that is directly called in the @change event handler. So it will not get the default $event parameter - the special variable that carries the arguments from child component, unless you include it. In your code, this is the missing part.

Ref: https://vuejs.org/guide/events.html#Methods-in-Inline-Handlers

In the sample jsFiddle implementation, the $event is only the event arguments from child component, not a DOM event. My alterProperty method (in parent component) works as follows:

alterProperty: function(propToChange, newValue) {
    this.userInfo[propToChange] = newValue;
}

The jsFiddle also outputs the object on parent component, which gets modified as expected.

Edit: Additional Notes

Your child component should not bind this.value directly to your input element, as this.value is passed via props. If you try to do that, you will get a console error messsage like:

[Vue warn]: Avoid mutating a prop directly...

To avoid that, I have used a local computed property - textFieldValue, which has its getter and setter methods. While getter simply returns this.value, the setter is the one that sends the change event back to parent component, without touching this.value that is passed via props.

like image 175
Mani Avatar answered Sep 18 '22 07:09

Mani