Search code examples
vue.jsbootstrap-vue

VueJS - Is there a way to conditionally apply a transition?


What I would like to do is create an alert box component with a custom reveal transition that is optional, something like this (edited for brevity):

<template>
    <transition v-if="withTransition">
        <b-alert v-bind="this.$attrs" />
    </transition>
</template>

I will have a withTransition prop that ideally will conditionally render only the transition effect, and not affect the rendering of the alert box.

v-if and v-show won't work because those properties would show and hide the alert component as well. Plus, AFAIK <transition> does not render as a DOM element, so I'm not sure how that could be conditionally rendered, if at all.

Any suggestions?


Solution

  • You can use dynamic transitions and bind to a transition name (using a computed property) that does nothing when you want the effect disabled.

    For example...

    new Vue({
      el: '#app',
      data: () => ({ withTransition: true, show: false }),
      computed: {
        computedTransition () {
          return this.withTransition && 'fade'
        }
      }
    })
    .alert {
      background-color: #f99;
      border: 1px solid #f66;
      padding: 1rem;
    }
    
    .fade-enter-active, .fade-leave-active {
      transition: opacity .5s;
    }
    .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
      opacity: 0;
    }
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    
    <div id="app">
      <p>
        <label>
          With transition:
          <input type="checkbox" v-model="withTransition"/>
        </label>
      </p>
      <p><button type="button" @click="show = !show">Toggle alert</button></p>
      <transition :name="computedTransition">
        <p class="alert" v-if="show">Something happened</p>
      </transition>
    </div>