vue.jsalertvuetify.js

How to create an alert the fade after a duration in Vuetify?


How to create an Alert in Vuetify that fade after specified number of seconds, similarly to the alerts in Bootstrap Vue. I tried this:

<template>
  <transition name="fade">
    <v-alert v-show="visible" v-bind="$attrs" v-on="$listeners">
      <slot></slot>
    </v-alert>
  </transition>
</template>

<script>
export default {
  inheritAttrs: true,
  data() {
    return {
      visible: true,
      timer: null
    };
  },
  props: {
    duration: {
      required: true,
      type: Number
    }
  },
  methods: {
    fade() {
      let value = parseInt(Math.max(this.duration, 0));
      if (value != 0)
        this.timer = setTimeout(() => (this.visible = false), 1000 * value);
    }
  },
  mounted() {
    this.fade();
  }
};
</script>

Usage in other components:

    <vt-alert
      v-if="hasMessage()"
      :type="message.type"
      :duration="message.duration"
    >{{message.body}}</vt-alert>

hasMessage is utility function which check if the message is set.

But this did not work. More details here,


Solution

  • No need for so much code and custom ideas :) Use vuetify API (Less code = easier to maintain):

    https://vuetifyjs.com/en/components/alerts/#api

    A. Show/Hide

    The alert get value (false => hide. True => show).

    <v-alert :value="alert">
    
    data () {
      return {
       alert: false,
    }
    

    Toggle alert to true/false on click, hover, timer or any logic you want.

    Docs toogle example: https://vuetifyjs.com/en/components/alerts/#transition

    B. transition props

    Use any build-in transition you want. Transitions List here: https://vuetifyjs.com/en/styles/transitions/#motion

    <v-alert transition="fade-transition">

    A+B: Basic "hello world" example

    On click show alert & slide-y-transition out after 3 seconds.

    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data () {
        return {
          alert: false,
        }
      },
      // define methods under the `methods` object
      methods: {
        hide_alert: function (event) {
          console.log('Hide')
          // `event` is the native DOM event
          window.setInterval(() => {
            this.alert = false;
            console.log("hide alert after 3 seconds");
          }, 3000)    
        }
      },
      mounted: function () {
        if(alert){
          this.hide_alert();
        }
      }
    })
    <link href="https://cdn.jsdelivr.net/npm/vuetify@2.2.18/dist/vuetify.min.css" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"/>
    
    <div id="app">
      <v-app id="inspire">
        <div>
          <div class="text-center mb-4">
            <v-btn
                   color="primary"
                   @click="alert = true"
                   >
              Show alert? {{alert}}
            </v-btn>
          </div>
          <v-alert
                   :value="alert"
                   color="pink"
                   dark
                   border="top"
                   icon="mdi-home"
                   transition="slide-y-transition"
                   >
            Phasellus tempus. Fusce ac felis sit amet ligula pharetra condimentum. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. Pellentesque posuere. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo.
    
            Phasellus nec sem in justo pellentesque facilisis. Phasellus magna. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. In hac habitasse platea dictumst. Praesent turpis.
          </v-alert>
        </div>
      </v-app>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.2.18/dist/vuetify.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>

    Extra features example

    Show timer (3..2..1) when the alert visible + toggle the alert on a button click.

    About dismissible the best idea is to create a custom X button (And use the same show/hide function) ***Until the API gives more options related to this feature (Styling/position and so on).

    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data () {
        return {
          message: "show alert? - ",
          alert: false,
          countDown: {
            timer: "3",
            show: false
          },
        }
      },
      // define methods under the `methods` object
      methods: {
        show_alert_and_fade: function(){
          /* toogle alert on click */
          this.alert = !this.alert; 
          /* hide alert after 3 seconds */
          this.resetTimer();
          this.countDownTimer();
          /*  If alert visible - setTimeout() => only executed once */
          if(this.alert == true){
            myTimer = window.setTimeout(() => {
              this.alert = false;
              console.log("Case 1: Time ends - hide alert");
            }, 3000);
          }else{
            /* If alert hidden - clear setTimeout */
            console.log("Case 2: User Hide alert by click - stop setTimeout");
            clearTimeout(myTimer);
            this.resetTimer();
          }
        },
        dismissible_close (value) {
          this.alert = value;
          this.resetTimer();
        },
        /*  recursion function - run time if remain time and alert if visible */ 
        countDownTimer() {
          if(this.countDown.timer > 0 && this.alert) {
            this.countDown.show = true;
            var myTimer = setTimeout(() => {
              this.countDown.timer -= 1;
              this.countDownTimer();
            }, 1000)
            }
          else{
            /* do something */
            this.resetTimer();
          }
        },
        resetTimer(){
          this.countDown.timer = 3;    
        },
        hideTimer(){
          this.countDown.show = false; 
        }
      }
    })
    body{
      padding: 10px;
    }
    
    #close_btn{
      position: absolute;
      right: 6px;
      top: 12px;
    }
    <link href="https://cdn.jsdelivr.net/npm/vuetify@2.2.18/dist/vuetify.min.css" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"/>
    
    <div id="app">
      <v-app id="inspire">
        <div>
          <div class="text-center mb-4">
    
            <!-- remove countDown for demo only -->
    
            <v-btn
                   v-bind:color="alert ? 'success' : 'error'"
                   @click="show_alert_and_fade"
                   v-bind:class="{ active: alert }"
                   >
              {{message}} <b> {{alert}}</b>
    
            </v-btn>
    
            <v-badge v-if="alert"
                     :content="countDown.timer"
                     :value="countDown.timer"
                     color="red"
                     overlap
                     >
            </v-badge>
          </div>
          <v-alert
                   :value="alert"
                   color="success"
                   dark
                   border="top"
                   icon="mdi-home"
                   transition="slide-y-transition"
                   @input="dismissible_close"
                   >
            <div id="close_btn">
              <v-btn  color="success" fab x-small @click="show_alert_and_fade">
                <v-icon>mdi-close</v-icon>
              </v-btn>
            </div>
    
            <div class="pt-6 pr-6">
              <p>
                Phasellus tempus. Fusce ac felis sit amet ligula pharetra condimentum. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. Pellentesque posuere. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo.
              </p>
              <p>
                Phasellus nec sem in justo pellentesque facilisis. Phasellus magna. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. In hac habitasse platea dictumst. Praesent turpis.
              </p>
    
            </div>
          </v-alert>
        </div>
      </v-app>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.2.18/dist/vuetify.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>