adnanmuttaleb
adnanmuttaleb

Reputation: 3624

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,

Upvotes: 5

Views: 22606

Answers (1)

Ezra Siton
Ezra Siton

Reputation: 7781

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/[email protected]/dist/vuetify.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/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/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/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/[email protected]/dist/vuetify.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/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/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>

Upvotes: 17

Related Questions