Binding method result to v-model with Vue.js

Agree with the :value and @change combination greenymaster. Even when we split the computed property in get/set, which is help, it seems very complicated to make it work if you require a parameter when you call for get(). My example is a medium sized dynamic object list, that populates a complex list of inputs, so:

  • I can't put a watch easily on a child element, unless I watch the entire parent list with deep, but it would require more complex function to determine which of the innter props and/or lists changed and do what fromthere
  • I can't use directly a method with v-model, since, it works for providing a 'get(param)' method (so to speak), but it does not have a 'set()' one
  • And the splitting of a computed property, have the same problem but inverse, having a 'set()' but not a 'get(param)'

v-model expressions must have a get and set function. For most variables this is pretty straight forward but you can also use a computed property to define them yourself like so:

data:function(){
    return { value: 5 }
},
computed: {
    doubleValue: {
        get(){
            //this function will determine what is displayed in the input
            return this.value*2;
        },
        set(newVal){
            //this function will run whenever the input changes
            this.value = newVal/2;
        }
    }
}

Then you can use <input v-model="doubleValue"></input>

if you just want the tag to display a method result, use <tag>{{method_name(data_attribute)}}</tag>


Years later, with more experience, I found out that is it easier to bind :value instead of using v-model. Then you can handle the update by catching @change.

Edit (per request):

<input :value="myValue" @change="updateMyValue">

...

methods: {
  updateMyValue (event) {
    myValue = event.target.value.trim() // Formatting example
  }
}

And in a child component:

// ChildComponent.vue

<template>
  <button
    v-for="i in [1,2,3]">
    @click="$emit('change', i) />
</template>

// ParentComponent.vue

<template>
  <child-component @change="updateMyValue" />
</template>

<script>
import ChildComponent from './child-component'

export default {
  components: {
    ChildComponent
  },
  data () {
    return {
      myvalue: 0
    }
  },
  methods: {
    updateMyValue (newValue) {
      this.myvalue = newValue
    }
  }
}
</script>

Tags:

Vue.Js