Add a Sidebar Menu to a Vue App with vue-sidebar-menu

John Au-Yeung - Jan 20 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

We can add a sidebar menu with into a Vue app with the vue-sidebar-menu library.

In this article, we’ll look at how to us it to add the menu.

Installation

We can install the package by running:

npm i vue-sidebar-menu
Enter fullscreen mode Exit fullscreen mode

Adding the Menu

We use the sidebar-menu component to do that.

To do that, we write:

main.js

import Vue from "vue";
import App from "./App.vue";
import VueSidebarMenu from "vue-sidebar-menu";
import "vue-sidebar-menu/dist/vue-sidebar-menu.css";
Vue.use(VueSidebarMenu);
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");
Enter fullscreen mode Exit fullscreen mode

App.vue

<template>
  <div id="app">
    <sidebar-menu :menu="menu"/>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      menu: [
        {
          header: true,
          title: "Main Navigation",
          hiddenOnCollapse: true
        },
        {
          href: "/",
          title: "Dashboard",
          icon: "fa fa-user"
        },
        {
          href: "/charts",
          title: "Charts",
          icon: "fa fa-pie-chart",
          child: [
            {
              href: "/charts/sublink",
              title: "Sub Link"
            }
          ]
        }
      ]
    };
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

We register the library in main.js .

Then we add it to our component.

href has the URL. title has the menu entry title.

icon has the menu class.

In index.html , we add the Font Awesome library to add our icons”

<link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
      integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
      crossorigin="anonymous"
    />
Enter fullscreen mode Exit fullscreen mode

Use With Vue Router

We can use the library with Vue Router. To do this, we add Vue Router and the router-view component.

main.js

import Vue from "vue";
import App from "./App.vue";
import VueSidebarMenu from "vue-sidebar-menu";
import "vue-sidebar-menu/dist/vue-sidebar-menu.css";
import VueRouter from "vue-router";
Vue.use(VueRouter);
Vue.use(VueSidebarMenu);
Vue.config.productionTip = false;

const Dashboard = { template: "<div>dashboard</div>" };
const Charts = { template: "<div>charts</div>" };

const routes = [
  { path: "/dashboard", component: Dashboard },
  { path: "/charts", component: Charts }
];

const router = new VueRouter({
  routes
});

new Vue({
  router,
  render: (h) => h(App)
}).$mount("#app");
Enter fullscreen mode Exit fullscreen mode

App.vue

<template>
  <div id="app">
    <div style="display: flex; justify-content: space-between">
      <div>
        <sidebar-menu :menu="menu"/>
      </div>
      <div>
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      menu: [
        {
          header: true,
          title: "Main Navigation",
          hiddenOnCollapse: true
        },
        {
          href: "/dashboard",
          title: "Dashboard",
          icon: "fa fa-user"
        },
        {
          href: "/charts",
          title: "Charts",
          icon: "fa fa-pie-chart"
        }
      ]
    };
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

We added the components and use them in the routes array.

Then we pass routes in the VueRouter component.

In App.vue , we have the same menu items.

The only thing we added is the router-view to display the components that are mapped to the routes.

Slots

We can custom the content of our menu by populating various slots.

To do this, we add:

<template>
  <div id="app">
    <div style="display: flex; justify-content: space-between">
      <div>
        <sidebar-menu :menu="menu">
          <div slot="header">header</div>
          <div slot="footer">footer</div>
          <span slot="toggle-icon">
            <i class="fa fa-caret-square-o-down"></i>
          </span>
          <span slot="dropdown-icon">dropdown-icon</span>
        </sidebar-menu>
      </div>
      <div>
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      menu: [
        {
          header: true,
          title: "Main Navigation",
          hiddenOnCollapse: true
        },
        {
          href: "/dashboard",
          title: "Dashboard",
          icon: "fa fa-user"
        },
        {
          href: "/charts",
          title: "Charts",
          icon: "fa fa-pie-chart"
        }
      ]
    };
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

We populate the header slot to change the header.

footer slot changes the footer.

toggle-icon changes the toggle icon at the bottom of the menu.

dropdown-icon sets the dropdown icon.

Conclusion

We can add a sidebar menu to our Vue app with the vue-sidebar-menu library.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .