Vuetify: [Feature Request] Snackbar @close Event

Created on 13 Jun 2017  路  14Comments  路  Source: vuetifyjs/vuetify

There is no way to create a global notification system. With the ability to send a notification from anywhere in the application.

You could use a storage module. Implement in it a queue of notifications. And in this case, you need to delete the notification from storage after the snackbar is hidden (after the animation)

question

Most helpful comment

@HarveyMoony You can see my temporary solution - https://codesandbox.io/s/407zvllxw4
I've typed a separate component that holds the message queue. However, the delay between messages is realized using the usual timeout. As for me - this is not the best and not a tedious decision.

But I think it would be better if this functionality was provided by the <v-snackbar> component

All 14 comments

@cawa-93 how about using a snackbar (or anything similar) which has a computed variable based on vuex like this:

YourNotification.vue

export default {
  computed:{
    notification(){
     return this.$store.state.globalNotifications
   }
  }
}

Place this component anywhere in your layout only once.. then all you need to do is pushing into the vuex store any globalNotification. Would this help?

I don't see the point of implementing someting on the side of vuetify.. thats a perfect usecase for the global state management vuex in my opinion.

Yes, I'm talking about this. But I need to somehow track the moment when the bar was closed to remove it from the store. If you display several snackbars, they overlap each other. Therefore, it is important to handle the event when one bar is completely hidden to display the next one. Rotation of notifications Example:

<template>
  <div>
    <v-snackbar
      v-model="show"
      @close="removeFromStore"
      >{{ notification.text }}
        <v-btn flat class="pink--text" @click.native="show = false">Close</v-btn>
    </v-snackbar>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        show: false
      }
    }
    computed: {
      notification(){
        return this.$store.state.globalNotifications[0]
      }
    },
    mounted() {
      if (this.notification) {
        this.show = true
      }
    },
    methods: {
      removeFromStore() {
        this.$store.dispatch('shiftNotification')
        if (this.notification) {
          this.show = true
        }
      }
    }
  }
</script>

I represent this order of work:

  1. this.show set to true
  2. Animation starts. The bar appears smoothly
  3. After the timeout expires or after clicking the button this.show set to false
  4. Animation starts. The bar disappears smoothly
  5. At the end of the animation, the emit event close
  6. In the handler We perform some actions. In my example, a notification is removed from the store, and if there is another, the bar is shown again.

@cawa-93 can't you watch the show variable:

watch:{
  show(value){
    if(value === false){
     this.removeFromStore()
   }
  }
}

maybe a short timeout might be necessary.. but I haven't tested it. Just been curious

The fact is that the parameter show changes BEFORE the bar completely disappears. As a result, a new notification appears instantly. I want to run the removeFromStore method only after the current bar disappears completely (the animation of the disappearance is completed).

It also leads to the second problem: the timeout is not reset.

https://codepen.io/cawa-93/pen/xrOzvp?editors=1010#0

maybe this helps: https://codepen.io/anon/pen/bRexNR?editors=1011
I simply show the snackbar as long there are items available (setting timeout to false). Is that a solution?

Nope. This is not what I want to get

And delaying the next snackbar like dohomi suggested is not a solution either?

https://codepen.io/anon/pen/KqMxae?editors=1010#0

@nekosaur Yes This is the solution. But as for me, this is a very rough workaround. In reality, the delay before the new notification is displayed is not related to the previous one. Because of which they can potentially overlap.

Not to mention the reassigned code. It would be much easier to have a special event that would shoot immediately after the end of animation and reset timeout

It's strange that the problem has not been solved yet.
In fact, in the current version Snackbar can be used in the simplest case. But very often, when a single notification is displayed, you will likely need to display a few more in a short time.
I think Quasar has a great solution http://quasar-framework.org/components/notify.html. It would be healthy to do something like this and in Vuetify

I'm using the Vuetify, and unfortunately the Snackbar component is not suitable for me. Is it planned to fix this in the near future?

@HarveyMoony You can see my temporary solution - https://codesandbox.io/s/407zvllxw4
I've typed a separate component that holds the message queue. However, the delay between messages is realized using the usual timeout. As for me - this is not the best and not a tedious decision.

But I think it would be better if this functionality was provided by the <v-snackbar> component

@cawa-93 Please excuse me if I understood the problem incorrectly but why don't you simply use :value and @input instead of v-model on <v-snackbar/>?
Here is my working solution to handle this specific problem:

<template>
  <v-snackbar :value="shown" @input="$emit('close')">
    Hello world! this is an awesome message!
    <v-btn @click="$emit('close')">Close Me!</v-btn>
  </v-snackbar>
</template>

<script>
export default {
  name : 'Notify',
  props: {
    shown: {
      type   : Boolean,
      default: false,
    },
  },
}
</script>

And call it like this:

<template>
   <div>
      <v-btn @click="showSnackbar = true">Show the notification</v-btn>
      <notify :shown="showSnackbar" @close="showSnackbar = false"/> <!-- @close will be called whether snackbar is timed-out or is manually closed -->
   </div>
</template>

<script>
export default {
  name : 'SomeContainer',
  data   : () => {
    return ({
      showSnackbar: false
   })
  },
}
</script>

Well you can queue it of course.

@AmirrezaNasiri I do not know how it works now. At the time when I created this issue, the @input fired before exit animation completed.

If you have any additional questions, please reach out to us in our Discord community.

I used Provide and inject instead of using Vuex and this is my solution
https://codesandbox.io/s/jz3yz3x93w

Was this page helpful?
0 / 5 - 0 ratings