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:
- You have to use an arrow function, otherwise
this
will not reference your component. - 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
(orbeforeDestroy
) withthis.emitter.off...
. Actually not really optional, it is at least really bad code style to not do that