Working with Vuetify: improvements – part 5

Posted by in Javascript and TypeScript

We continue learning with the series Working with Vuetify, (part 2) where we have started working with one of the predefined templates, and have been adapting it to work without NodeJs or Webpack or compilation: all and only Javascript.

In parts 3 and 4, we’ve learned about VueX, and the modules as well, but we’ve hardly included any functionality. Now it’s time to work with the menu, which was hardly touched before, except to include the name and version saved in the store.

If you like this serie, just let me know and also, you can contribute to mantintain this blog.

Preparing the options for the menu on the left

In the menu, in data, two lists are included: the first one corresponds to the top, and the second one to the subscriptions. We are going to eliminate the second one to focus on the first one (that is to say, we will eliminate item2 and also source and we will not need the getuser method anymore).

In turn, we will include new properties: menu (to know which component to show), and colores (to give homogeneous format to the application, and where we have selected the orange). Also, to control the menu on the left, we’ll set draw to false (or true, if we want it to start already visible). At the end, this part of the component looks like this:

data() {
		return {
			drawer: true,
            items: [
                { icon: 'trending_up', text: 'Most Popular', action: 'popular', color_item_text: 'red--text', icon_class: 'red--text' },
                { icon: 'subscriptions', text: 'Subscriptions', action: 'suscripciones' },
                { divider: true , class: 'blue' },
                { icon: 'history', text: 'History', action: 'historia' },
                { icon: 'featured_play_list', text: 'Playlists', action: 'playlist'},
                { icon: 'watch_later', text: 'Watch Later', action: 'later' },
            ],
			colores: {
				color: 'orange',
				color_list: 'blue lighten-4',
				color_item_text: 'red',
			},
			menu: '',
		}
	},

The dynamic loading of the menu is produced by this code, associated with the item property on the template’s code:

<v-list-item
          v-for="item in items"
          :key="item.text"
          link
        >
          <v-list-item-action>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-action>
          <v-list-item-content>
            <v-list-item-title>
              {{ item.text }}
            </v-list-item-title>
          </v-list-item-content>
        </v-list-item>

However, I have ended up creating a new component to improve the previous code. You will have noticed that the item variable extends the possibilities, allowing it to assign a certain colour to each option, as well as a different colour to the icon. But the most interesting thing is to include an action property that will tell us which action to develop:

const sublistado2 = Vue.component('sublistado2', {
	props: {
		menulist: { required: true, type: Array }, 
		colores: { 
			required: false,
			type: Object,
			default: function () { return {} }
		},
	},
	data() {
		return {
			color_list_def: 'grey lighten-4',
			color_item_text_def: 'black--text',
		}
	}, 
	computed: {
		color_list() { return this.colores.color_list || this.color_list_def },
		color_item_text() { return this.colores.color_item_text || this.color_item_text_def },
	},
	methods: {
		accion(item) {
			this.$emit('accion', item.action);
		},
	},
	template: `
	<v-list dense :class="color_list">
		<template v-for="(item, i) in menulist">
			  <v-layout v-if="item.heading" :key="i" align-center>
				<v-flex xs12>
				  <v-subheader v-if="item.heading" :class="item.class">
					{{ item.heading }}
				  </v-subheader>
				</v-flex>
			  </v-layout>
			  
			  <v-list-item v-else-if="item.text" :key="i" @click.stop="accion(item)">
				<v-list-item-action v-if="item.icon">
				  <v-icon :class="item.icon_class">{{ item.icon }}</v-icon>
				</v-list-item-action>
				<v-list-item-content>
				  <v-list-item-title :class="item.color_item_text">
					{{ item.text }}
				  </v-list-item-title>
				</v-list-item-content>
			  </v-list-item>
			  <v-divider v-if="item.divider" :key="i" class="my-1" :class="item.class"></v-divider>
		</template>
		<slot ></slot>
	</v-list>	
	`
});

This new component has more possibilities and options, but also, it reduces the menu code, and can even be configured to include separators:

<sublistado2
			:menulist="items"
			:colores="colores"
			@accion="accion"
		></sublistado2>

As you can see, we have an event called action, which must be controlled, with the action method whose code is:

accion(action) {this.menu = action; },

And this is the way to know what the user is doing. But, not only this: you can extend the template as you want (or need) with new functionality.

In the main zone of the template, let’s add a label to show what the user has selected:

<v-main>
      <v-container class="fill-height">
        <v-row
          justify="center"
          align="center"
        >
          
		  <v-flex xs12 v-if="menu">
					<div align="center">
					{{ menu }}
					</div>
				  </v-flex>
		  
        </v-row>
      </v-container>
    </v-main>

And the result is, for example, when you click on Subscriptions:

Plantilla mejorada

And so far, all that has been included in the Working with Vuetify series, where the rest is already at your disposal, since you already know how to use a predefined vuetify template. I can fo even further with a final entrance by using the login form!

The truth is that I wish someone had exposed this to me that I have done before!

Happy coding!