Reusable Alerts in Vuetify

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 -

<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 -

<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.

<!-- ./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.

<!-- ./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.

// ./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.

comments powered by Disqus