Jip Helsen
Jip Helsen

Reputation: 1346

v-if not updating after eventbus event

Hi I'm having problems with a v-if that's not updating after receiving an eventbus event. This is my code :

<template>
  <div class="main">
      <button  v-if="inCreationMode()">
        Make a new snippet
      </button>
      <button v-if="mode ==='edit'">Push edits</button>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      mode: "creation",
    };
  },
  created() {
    this.emitter.on("editSnippet", snippet => function(snippet){
      this.mode = "edit";
    });
  },
};
</script>

I tried replacing the v-if conditions by functions :

    <template>
      <div class="main">
          <button  v-if="inCreationMode()">
            Make a new snippet
          </button>
          <button v-if="inEditMode()">Push edits</button>
        </div>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          mode: "creation",
        };
      },
      created() {
        this.emitter.on("editSnippet", snippet => function(snippet){
          this.mode = "edit";
        });
      },
      methods:{
      inCreationMode() {
      return this.mode === "creation";
        },
       inEditMode(){
          return this.mode ==="edit";
         }
      }
    };
    </script>

I tried using this.$forceUpdate() as well. Does anyone know a solution to this problem. Thanks in advance.

Upvotes: 0

Views: 288

Answers (2)

v-moe
v-moe

Reputation: 1443

I see many problems here, that could all be part of the reason why it's not working. Given that you have defined your emitter to be new Vue(), and added that to the Vue prototype correctly and that the component that emits the event does it by this.emitter.emit('editSnippet'). You have to:

Replace

this.emitter.on("editSnippet", snippet => function(snippet){ this.mode = "edit"; });

with

this.emitter.on("editSnippet", () => { this.mode = "edit";});

Reasons:

  1. You have to use an arrow function, otherwise this will not reference your component.
  2. Your callback should be a function that "does something", not one that returns a function (that won't be called)

Further improvements (optional):

  • Use computed props instead of methods as described in the other answer
  • Cleanup the listener in beforeUnmount (or beforeDestroy) with this.emitter.off... . Actually not really optional, it is at least really bad code style to not do that

Upvotes: 2

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

You should use computed properties instead of methods in this case :

   <template>
      <div class="main">
          <button @click="  inCreationMode() " v-if="inCreationMode">
            Make a new snippet
          </button>
          <button v-if="inEditMode">Push edits</button>
        </div>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          mode: "creation",
        };
      },
      created() {
        this.emitter.on("editSnippet", snippet => function(snippet){
          this.mode = "edit";
        });
      },
      computed:{
      inCreationMode() {
      return this.mode === "creation";
        },
       inEditMode(){
          return this.mode ==="edit";
         }
      }
    };
    </script>

Note : remove the () from the v-if value

Upvotes: 2

Related Questions