This example will register an vuex module dynamically for storing custom notifications that can automatically dismissed
notifications.js
resolve vuex store and define some constants
//Vuex store previously configured on other side
import _store from 'path/to/store';
//Notification default duration in milliseconds
const defaultDuration = 8000;
//Valid mutation names
const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED';
const NOTIFICATION_DISMISSED = 'NOTIFICATION_DISMISSED';
set our module initial state
const state = {
Notifications: []
}
set our module getters
const getters = {
//All notifications, we are returning only the raw notification objects
Notifications: state => state.Notifications.map(n => n.Raw)
}
set our module Actions
const actions = {
//On actions we receive a context object which exposes the
//same set of methods/properties on the store instance
//{commit} is a shorthand for context.commit, this is an
//ES2015 feature called argument destructuring
Add({ commit }, notification) {
//Get notification duration or use default duration
let duration = notification.duration || defaultDuration
//Create a timeout to dismiss notification
var timeOut = setTimeout(function () {
//On timeout mutate state to dismiss notification
commit(NOTIFICATION_DISMISSED, notification);
}, duration);
//Mutate state to add new notification, we create a new object
//for save original raw notification object and timeout reference
commit(NOTIFICATION_ADDED, {
Raw: notification,
TimeOut: timeOut
})
},
//Here we are using context object directly
Dismiss(context, notification) {
//Just pass payload
context.commit(NOTIFICATION_DISMISSED, notification);
}
}
set our module mutations
const mutations = {
//On mutations we receive current state and a payload
[NOTIFICATION_ADDED](state, notification) {
state.Notifications.push(notification);
},
//remember, current state and payload
[NOTIFICATION_DISMISSED](state, rawNotification) {
var i = state.Notifications.map(n => n.Raw).indexOf(rawNotification);
if (i == -1) {
return;
}
clearTimeout(state.Notifications[i].TimeOut);
state.Notifications.splice(i, 1);
}
}
Register our module with defined state, getters, actions and mutation
_store.registerModule('notifications', {
state,
getters,
actions,
mutations
});
Usage
componentA.vue
This components displays all notifications as bootstrap's alerts on top right corner of screen, also allows to manually dismiss each notification.
<template>
<transition-group name="notification-list" tag="div" class="top-right">
<div v-for="alert in alerts" v-bind:key="alert" class="notification alert alert-dismissible" v-bind:class="'alert-'+alert.type">
<button v-on:click="dismiss(alert)" type="button" class="close" aria-label="Close"><span aria-hidden="true">×</span></button>
<div>
<div>
<strong>{{alert.title}}</strong>
</div>
<div>
{{alert.text}}
</div>
</div>
</div>
</transition-group>
</template>
<script>
export default {
name: 'arc-notifications',
computed: {
alerts() {
//Get all notifications from store
return this.$store.getters.Notifications;
}
},
methods: {
//Manually dismiss a notification
dismiss(alert) {
this.$store.dispatch('Dismiss', alert);
}
}
}
</script>
<style lang="scss" scoped>
$margin: 15px;
.top-right {
top: $margin;
right: $margin;
left: auto;
width: 300px;
//height: 600px;
position: absolute;
opacity: 0.95;
z-index: 100;
display: flex;
flex-wrap: wrap;
//background-color: red;
}
.notification {
transition: all 0.8s;
display: flex;
width: 100%;
position: relative;
margin-bottom: 10px;
.close {
position: absolute;
right: 10px;
top: 5px;
}
> div {
position: relative;
display: inline;
}
}
.notification:last-child {
margin-bottom: 0;
}
.notification-list-enter,
.notification-list-leave-active {
opacity: 0;
transform: translateX(-90px);
}
.notification-list-leave-active {
position: absolute;
}
</style>
Snippet for add notification in any other component
//payload could be anything, this example content matches with componentA.vue
this.$store.dispatch('Add', {
title = 'Hello',
text = 'World',
type = 'info',
duration = 15000
});