A common requirement in any data-driven application is to show any alerts including error or warning messages at a standard location within a Vue component. This is easily accomplished using v-alert
in Vuetify, but it is a good idea to use it in combination with a snackbar.
Consider a typical component Account.vue
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<template>
<div class="account">
<v-layout row wrap>
<v-flex xs12 class="title">
Accounts
</v-flex>
<v-flex xs12>
<AccountList></AccountList>
</v-flex>
<v-flex xs12>
<AccountDetail></AccountDetail>
</v-flex>
</v-layout>
</div>
</template>
|
The requirement is to show informational messages, errors or warnings - either from back-end applications or front-end validation messages etc. as a popup alert.
We will split this requirement into two -
- a static alert at the top
- floating alert for short pop-up messages (preferably timed to vanish after a few seconds!)
Alert
An example of alert in Vuetify -
We will use this alert in our Account.vue
component -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<template>
<div class="account">
<v-layout row wrap>
<v-flex xs12 class="title">
Accounts
</v-flex>
<v-flex xs12>
<v-alert type="warning" :value="displayError" dismissible
>{{displayError}}</v-alert
>
</v-flex>
<v-flex xs12>
<AccountList></AccountList>
</v-flex>
<v-flex xs12>
<AccountDetail></AccountDetail>
</v-flex>
</v-layout>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from "vuex";
import AccountList from "../components/AccountList";
import AccountDetail from "../components/AccountDetail";
export default {
components: { AccountList, AccountDetail },
computed: {
...mapState("accounts", ["accounts", "displayError"])
}
};
</script>
|
displayError
is shown when there are any warning or error messages populated in the Vuex state variable. v-alert
takes care of displaying the message as static alerts at the top of the page. We can use this for warnings or error messages. These messages are largely static and are reset across distinct operations or events.
Snackbar
We will implement the short (typically timed) messages as a snackbar.
These messages are best implemented at the app level instead of individual components.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!-- ./App.vue -->
<template>
<v-app>
<Snackbar />
<v-content>
<router-view></router-view>
</v-content>
</v-app>
</template>
<script>
import Snackbar from "@/components/Snackbar";
export default {
components: { Snackbar }
};
</script>
|
Create a snackbar component to show the snackbar with specified colour and for pre-defined time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<!-- ./components/Snackbar.vue -->
<template>
<v-snackbar v-model="show" :top="top" :color="color">
{{message}}
<v-btn flat color="accent" @click.native="show = false">
<v-icon>close</v-icon>
</v-btn>
</v-snackbar>
</template>
<script>
export default {
data() {
return {
show: false,
top: true,
message: "",
color: "",
timeout: 5000
};
},
created: function() {
this.$store.watch(
state => state.snackbar.snack,
() => {
const message = this.$store.state.snackbar.snack.message;
if (message) {
this.show = true;
this.message = message;
this.color = this.$store.state.snackbar.snack.color;
this.$store.commit("snackbar/setSnack", {});
}
}
);
}
};
</script>
|
Create a snackbar module in store. This will temporarily store the state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// ./store/snackbar.js
const getDefaultState = () => {
return {};
};
const state = getDefaultState();
export default {
namespaced: true,
name: "snackbar",
state: {
snack: {}
},
mutations: {
setSnack(state, showSnack) {
state.snack = { ...showSnack };
},
resetState(state) {
Object.assign(state, getDefaultState());
}
}
};
|
That’s about it! We now have two types of alerts in our application.