assaqqaf
assaqqaf

Reputation: 1585

VJs watching array element

I have problem with vm.$watch method it can watch a single variable.

I can't make it to watch array elements.

in the example below i can't watch the change on the two select box bellow:

Vue.directive('select', {
  twoWay: true,

  bind: function() {
    var optionsData
    var optionsExpression = this.el.getAttribute('options')
    if (optionsExpression) {
      optionsData = this.vm.$eval(optionsExpression)
    }
    // initialize select2
    var self = this
    $(this.el)
      .select2({
        data: optionsData
      })
      .on('change', function() {
        self.set(this.value)
      })
  },

  update: function(value) {
    $(this.el).val(value).trigger('change')
  },

  unbind: function() {
    $(this.el).off().select2('destroy')
  }
})

var vm = new Vue({
  el: '#el',
  data: {
    selected: [{
      country: 2
    }, {
      country: 1
    }],
    options: [{
      id: 1,
      text: 'USA'
    }, {
      id: 2,
      text: 'UK'
    }]
  }
})

vm.$watch('selected', function(newvalue, oldval) {
  alert('changed: ' + newvalue)
})
select {
  min-width: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.12.9/vue.min.js"></script>

<div id="el">
  <p>Selected: {{selected[0].country}}</p>
  <select v-select="selected[0].country" options="options">
    <option value="0">default</option>
  </select>
  
  <p>Selected: {{selected[1].country}}</p>
  <select v-select="selected[1].country" options="options">
    <option value="0">default</option>
  </select>
</div>

Upvotes: 0

Views: 790

Answers (1)

David K. Hess
David K. Hess

Reputation: 17246

You need to specify the deep option on your watch. The array isn't being modified, an object that it contains is being modified.

Vue.directive('select', {
  twoWay: true,

  bind: function() {
    var optionsData
    var optionsExpression = this.el.getAttribute('options')
    if (optionsExpression) {
      optionsData = this.vm.$eval(optionsExpression)
    }
    // initialize select2
    var self = this
    $(this.el)
      .select2({
        data: optionsData
      })
      .on('change', function() {
        self.set(this.value)
      })
  },

  update: function(value) {
    $(this.el).val(value).trigger('change')
  },

  unbind: function() {
    $(this.el).off().select2('destroy')
  }
})

var vm = new Vue({
  el: '#el',
  data: {
    selected: [{
      country: 2
    }, {
      country: 1
    }],
    options: [{
      id: 1,
      text: 'USA'
    }, {
      id: 2,
      text: 'UK'
    }]
  }
})

vm.$watch('selected', function(newvalue, oldval) {
  alert('changed: ' + newvalue)
}, {
    deep: true
})
select {
  min-width: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.12.9/vue.min.js"></script>

<div id="el">
  <p>Selected: {{selected[0].country}}</p>
  <select v-select="selected[0].country" options="options">
    <option value="0">default</option>
  </select>
  
  <p>Selected: {{selected[1].country}}</p>
  <select v-select="selected[1].country" options="options">
    <option value="0">default</option>
  </select>
</div>

Upvotes: 1

Related Questions