Sam
Sam

Reputation: 69

Vue JS: Setting computed property not invoking v-if

When a method sets a computed property, v-ifs are not getting invoked. I thought a computed property logically worked just like a 'regular' property.

// theState can't be moved into Vue object, just using for this example
var theState = false; 
var app = new Vue({
  el: '#demo',
  data: {
  },
  methods: {
     show: function() {
        this.foo = true;
     },
     hide: function() {
        this.foo = false;
     }
  },
  computed: {
    foo: { 
      get: function() {
        return theState;
      },
      set: function(x) {
        theState = x;
      }
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="demo">
  <input type=button value="Show" @click="show()">
  <input type=button value="Hide" @click="hide()">
  <div v-if="foo">Hello</div>
</div>

Am I doing something wrong?

Upvotes: 1

Views: 3905

Answers (2)

Daniel Beck
Daniel Beck

Reputation: 21514

Vue doesn't observe changes in variables outside the component; you need to import that value into the component itself in order for the reactivity to work.

var theState = false;  // <-- external variable Vue doesn't know about
var app = new Vue({
  el: '#demo',
  data: {
     myState: theState // <-- now Vue knows to watch myState for changes
  },
  methods: {
     show: function() {
       this.foo = true;
       theState = true; // <-- this won't affect the component, but will keep your external variable in synch
     },
     hide: function() {
        this.foo = false;
        theState = false; // <-- this won't affect the component, but will keep your external variable in synch
     }
  },
  computed: {
    foo: { 
      get: function() {
        return this.myState;
      },
      set: function(x) {
        this.myState = x;
      }
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="demo">
  <input type=button value="Show" @click="show()">
  <input type=button value="Hide" @click="hide()">
  <div v-if="foo">Hello</div>
</div>

(Edited to remove incorrect info; I forgot computed property setters existed for a while there)

Upvotes: 2

Aldarund
Aldarund

Reputation: 17621

You need to move theState into data. Otherwise it wont be reactive, so vue wont know when its changed, so v-if or any other reactivity wont work.

var app = new Vue({
  el: '#demo',
  data: {
    foo2: false,
    theState: false
 // 1
  },
  methods: {
     show: function() {
        this.foo = true;
     },
     hide: function() {
        this.foo = false;
     }
  },
  computed: {
    foo: {            // 2
      get: function() {
        return this.theState
      },
      set: function(x) {
        this.theState = x;
      }
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="demo">
  <input type=button value="Show" @click="show()">
  <input type=button value="Hide" @click="hide()">
  <div v-if="foo">Hello</div>
</div>

Upvotes: 1

Related Questions