Home » vue » Click triggered twice Vue.js

Click triggered twice Vue.js

Posted by: admin November 26, 2021 Leave a comment

Questions:

I have this code

displayGeneralTip (bool) {
  this.generalTip = bool
}
<div v-if="!generalTip" class="sm-exercise-tip sm-exercise-general-tip" @click="displayGeneralTip(true)">
  <img src="~assets/exercises/bulb.svg" alt="Ampoule éteinte">
  <span>Astuce</span>
</div>

<div v-if="generalTip" class="sm-exercise-block sm-exercise-general-tip-expand">
  <div class="general-tip-bulb-icon">
    <img src="~assets/exercises/lighted-bulb.svg" alt="Ampoule allumée">
  </div>
  <div class="sm-exercise-block-tip">Some text</div>
  <div class="sm-exercise-hide-answer" @click="displayGeneralTip(false)">
    <span>Masquer</span>
    <img src="~assets/exercises/eye.svg" alt="masquer">
  </div>
</div>

Initially, generalTip is set at false.
When clicking on the first div to display text, It works fine. The first block disappear, and the second one appears.

But when clicking on the div to hide answer (sm-exercise-hide-answer), It triggers the method displayGeneralTip with bool false, but just after it triggers the same method with bool true. As if we clicked on the second div and the first one too.

I tried to put the div with text else where in my page, and it works fine. The problem appears when the two divs must be on the same place on the page

Anyone had this problem ?

Answers:

as noted in the comment, either will work, self on first instance, or stop on second

displayGeneralTip (bool) {
  this.generalTip = bool
}
<div v-if="!generalTip" class="sm-exercise-tip sm-exercise-general-tip" @click.self="displayGeneralTip(true)">
  <img src="~assets/exercises/bulb.svg" alt="Ampoule éteinte">
  <span>Astuce</span>
</div>

<div v-if="generalTip" class="sm-exercise-block sm-exercise-general-tip-expand">
  <div class="general-tip-bulb-icon">
    <img src="~assets/exercises/lighted-bulb.svg" alt="Ampoule allumée">
  </div>
  <div class="sm-exercise-block-tip">Some text</div>
  <div class="sm-exercise-hide-answer" @click.stop="displayGeneralTip(false)">
    <span>Masquer</span>
    <img src="~assets/exercises/eye.svg" alt="masquer">
  </div>
</div>

but you may wonder why this is necessary…

the problem is that the two divs, (<div v-if="!generalTip" class="sm-exercise-tip sm-exercise-general-tip" and sm-exercise-block sm-exercise-general-tip-expand are rendered as the same diff, and the event listener from the first is passed on to the other щ(ºДºщ)

I reckon that it’s more of a bug than feature in this case, but with the more recent version of vue it’s very easy to fix by using key

<div :key="div1" v-if="!generalTip" class="sm-exercise-tip sm-exercise-general-tip" @click.self="displayGeneralTip(true)">
  <img src="~assets/exercises/bulb.svg" alt="Ampoule éteinte">
  <span>Astuce</span>
</div>
<div :key="div2" v-else class="sm-exercise-block sm-exercise-general-tip-expand">
  <div class="general-tip-bulb-icon">
    <img src="~assets/exercises/lighted-bulb.svg" alt="Ampoule allumée">
  </div>
  <div class="sm-exercise-block-tip">Some text</div>
  <div class="sm-exercise-hide-answer" @click.stop="displayGeneralTip(false)">
    <span>Masquer</span>
    <img src="~assets/exercises/eye.svg" alt="masquer">
  </div>
</div>

(also v-else is a great candidate for this kind of conditional)