François Romain
François Romain

Reputation: 14393

How to trigger a transition event on an element inside a component?

In a vue js app, how to trigger a transition event on an element inside a component, when this component leaves?

The element has a v-if="showElement", then showElement is set to false when the component transition fires on leave… but showElement is not changing in the view.

Here is a codepen: https://codepen.io/francoisromain-1472161924/pen/RGPYOb?editors=1111

and the code:

html:

<div id="app">
    <a @click="show = !show">Show {{ show }}</a>
    <page-component v-if="show"></page-component>
</div>

<script id="pageComponent" type="x-template">
    <div class="component" transition="component">
        <p>Component</p>
        <div v-if="showElement" class="element" transition="element">
            <p>Element</b>
         </div>
  </div>
</script>

js:

var pageComponent = Vue.extend({
    template: '#pageComponent',
    data() {
        return {
            showElement: false
        };
    },
    ready() {
        this.showElement = true;
    },
    beforeDestroy() {
        this.showElement = false;
    },
    transitions: {
        'component': {
            enter(el) {
            },
            leave(el) {
                this.showElement = false;
            }
        },
        'element': {
            enter(el) {
            },
            leave(el) {
            }
        }
    }
});

new Vue({
    el: '#app',
    components: {
        pageComponent
    },
    data: {
        show: true
    }
});

Upvotes: 3

Views: 4381

Answers (1)

Atinux
Atinux

Reputation: 1703

You need to use v-show instead of v-if because when the parent component is removed, everything attached from him is removed too so the element.leave transition is never called.

Your example updated: https://codepen.io/anon/pen/PGqxgX

var pageComponent = Vue.extend({
   template: '#pageComponent',
   data() {
      return {
         showElement: false
      };
   },
   ready: function () {
     this.showElement = true; 
   },
   transitions: {
      'component': {
         enter(el) {
            this.showElement = true;
         },
         leave(el, done) {
            this.showElement = false;
         }
      }
   }
});

new Vue({
   el: '#app',
   components: {
      pageComponent
   },
   data: {
      show: true
   },
   computed: {
      word: function() {
         return this.show ? 'hide' : 'show'
      }
   }
});
html {
   font-family: sans-serif;
}

a:hover {
   cursor: pointer;
}

.container {
   margin-top: 0px;
}

.component {
   margin-top: 0;
   opacity: 1;
   transition: all 2s;
}

.component-enter {
   margin-top: -150px;
   opacity: 0;
}

.component-leave {
   margin-top: -150px;
   opacity: 0;
}

.element {
   margin-left: 0;
   transition: all 2s;
   padding: 10px;
}

.element-enter {
   margin-left: 300px;
}

.element-leave {
   margin-left: 300px;
   background: red;
   color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
   <a @click="show = !show">Click to {{word}} component {{ show }}</a>
   <div class="container">
      <page-component v-show="show">
    </page-component>
   </div>
</div>

<script id="pageComponent" type="x-template">
	<div class="component" transition="component">
      <h1>Component</h1>
      <div v-show="showElement" class="element" transition="element">
      	<p><b>Element</b> {{ showElement }}</p>
         <p>Bug on 'leave': <br />this text should be red. <br />and 'element leave' in the console<br />It's not. Why?</p>
     </div>
  </div>
</script>

Upvotes: 3

Related Questions