Home > front end >  v-if not updating after eventbus event
v-if not updating after eventbus event

Time:12-01

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>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

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>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

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

CodePudding user response:

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

CodePudding user response:

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
  • Related