Role-based menus for navigation in Vuetify

What is your preferred way of showing role-based menus and buttons in toolbar and navigation menus?

A typical application may have many toolbars and navigation bars, each relevant to a specific set of users. You can then show/hide the elements based on the user role.

In smaller applications, I simply choose to show or hide the menu items on a single navigation bar. This is easier to develop and to maintain.

An example is below.

We will create a new component called Toolbar.vue which is included in the app. First, let us look at the template.

<!-- Toolbar.vue -->
<template>
  <div>
    <v-toolbar :clipped-left="clipped" flat fixed app>
      <v-toolbar-side-icon @click="navDraw = !navDraw"></v-toolbar-side-icon>
      <v-toolbar-title>
        <span>
          <img class="mr-2" src="../assets/my-logo.png" />
          <span class="title ">My Beautiful App</span>
        </span>
      </v-toolbar-title>
      <v-spacer>
        <v-btn flat to="/login" v-if="!isLoggedIn">
          <v-icon class="mr-1">fingerprint</v-icon>Login
        </v-btn>
      </v-spacer>
    </v-toolbar>

    <v-navigation-drawer :clipped="clipped" v-model="navDraw" width="200" app>
      <v-list v-if="isUser">
        <v-list-tile
          avatar
          v-for="(item, index) in userItems"
          dense
          :key="index"
          :to="item.to"
        >
          <v-list-tile-avatar>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-tile-avatar>
          <v-list-tile-title>{{ item.title }}</v-list-tile-title>
        </v-list-tile>
      </v-list>
      <v-list v-if="isAdmin">
        <v-list-tile
          avatar
          v-for="(item, index) in adminItems"
          dense
          :key="index"
          :to="item.to"
        >
          <v-list-tile-avatar>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-tile-avatar>
          <v-list-tile-title>{{ item.title }}</v-list-tile-title>
        </v-list-tile>
      </v-list>
    </v-navigation-drawer>
  </div>
</template>

What we have done so far is pretty simple -

  • Used the toolbar component from Vuetify
  • Introduced the logo and text on the main toolbar
  • We show a simple button on the toolbar based on whether user is logged in. We can as well show a similar menu to what has been used later in the navigation drawer
  • Introduced the Vuetify’s navigation drawer component
  • Create a menu that lists two sets of items - for user (which gets displayed only if user is logged in) and for admin (again, only if user is logged in and role is admin). The values that represent state of login, role etc. are used from Vuex store, which in turn gets it from the server (the values are set at login, logout and other related events)
  • The menus are dynamic - they get the title, icon and the link from data section

Let us then include all the states used in the <script> section.

<!-- Toolbar.vue -->
<script>
  import { mapGetters } from "vuex";
  export default {
    data() {
      return {
        clipped: true,
        navDraw: true,

        userItems: [
          { icon: "apps", title: "Dashboard", to: "/dashboard" },
          { icon: "money", title: "Bills", to: "/my-bill" }
        ],
        adminItems: [{ icon: "business", title: "Accounts", to: "/dashboard" }]
      };
    },
    computed: {
      ...mapGetters("user", ["isLoggedIn", "isAdmin", "isUser"])
    }
  };
</script>

script is pretty simple as well -

  • we refer to the various states from store - isLoggedIn, isAdmin, isUser
  • component-specific states (e.g. those required to open or close navigation drawer ) are housed within the component itself - clipped, navDraw and the menu items
  • menu items are picked up from data section. They have the title, icon and the link

That is it!

We now have a toolbar and navigation bar with menus that dynamically respond to the current role of a user.

comments powered by Disqus