Kendall
Kendall

Reputation: 5235

Using computed property setter and getter to update data properties

I have the following component markup

<select id="create-user-roles" class="form-control" v-bind="role">
                                  <option v-for="role in roles" :value="role.id">{{ role.label }}</option>
                              </select>

And have the following component

..........
data() {
      return {
        roles: [
        {name: 'something', id:0 },..,..,..,],
        form: {
            ......
            roles: null,
        }
      }
    },
    computed: {
      role: {
        get: function(){
          if(this.userData == undefined) return null;

          return this.userData.roles[0].id;
        },
        set: function(id) {
          console.log(id);
          var role = this.$data.roles.filter(function(o){
            return o.id === id
          }).name;
            console.log(role);
          this.$data.form.roles = [role];
            console.log(this.form.roles);
        }
      }
    },
...........

In my component methods function I do

this.form = Object.assign({}, this.userData)); // userData is a prop passed down from parent with {roles:[{id: 0, name: 'something' }]}

When I change the selection it doesn't update the form.roles with the role setter

Infact it doesn't appear that anything is fired!

What am I doing wrong here?

Upvotes: 1

Views: 15254

Answers (1)

asemahle
asemahle

Reputation: 20795

The main problem is v-bind. If you want a two-way binding between the value of the select element and role, you need to use v-model.

There is also a bug in the setter. The line

var role = this.$data.roles.filter(function(o){ 
    return o.id === id 
}).name; 

won't work because filter returns a list, not an item from that list.

With those changes made, your code should work. Here's a snippet with the changes:

Vue.component('child', {
	template: '#child',
  props: ['userData'],
  data() {
    return {
      roles: [
        {name: 'something0', id:0 },
        {name: 'something1', id:1 },
        {name: 'something2', id:2 },
      ],
      form: { roles: null }
    }
  },
  computed: {
    role: {
      get: function(){
        if(this.userData == undefined) return null;
        return this.userData.roles[0].id;
      },
      set: function(id) {
        var role = this.roles.filter(role => role.id === id)[0];
        Vue.set(this.form.roles, 0, role);
      }
    }
  },
  created: function() {
  	this.form = Object.assign({}, this.userData);
  }
});

new Vue({
  el: '#app',
  data: {
  	userData: {
    	roles: [ {id: 0, name: 'something' } ]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>

<div id="app">
  <child :user-data="userData"></child>
</div>

<template id="child">
  <div>
    <select v-model="role">
      <option v-for="role in roles" :value="role.id">{{ role.name }}</option>
    </select>
    <p>JSON.stringify(form):</p>
    <pre>{{JSON.stringify(form, null, 2)}}</pre>
  </div>
</template>

Upvotes: 1

Related Questions