Using Vue as an Angular alternative for Ionic: The Directives

We keep going on with the Ionic Vue fever!

This time we will see how we can we use Directives in an Ionic Vue application.

You will need to install the Ionic Vue stack from this previous tutorial.

Directives allows us to modify the DOM. They are generally attached to an Element and change its properties.

In this tutorial, we will recreate Angular's ngIf and ngShow Directives.

You might have already seen this great example in the Angular documentation and we will do something similar with Vue.

Custom Show Directive

Let's start by attaching our CustomShow Directive in the index.html file:

< div id = " app " > < div v-custom-show = ' false ' > Custom Show </ div > </ div >

A Vue Directive follows the kebab case naming convention complemented by a "v-" prefix.

Here we have a Vue Directive attached to a <div> Element which receives the boolean value false.

At this point, you should receive an error saying that the <custom-show> Directive is not registered and that's normal.

We will now create the custom-show.ts file:

export default { bind : function ( el , binding , vnode ) { const display = binding . value ? "block" : "none" ; el . style . display = display ; } } ;

We will export a new object which has a bind field.

We can use here a function which has three arguments:

el : The DOM element used (our <div>) binding: Some information on the data we passed to the Vue Directive (in our case the boolean value false) vnode: The Vue virtual node which contains information like the children, parent and much more information like:

Our aim here is displaying the <div> if the boolean value true is passed to this Directive.

For this example, we will retrieve the information from the binding's value property.

The ngShow or v-show only hide the DOM Element. We will do the same by modifying the style of the el argument, setting it to 'block' when it should be displayed and 'none' when it shouldn't.

That's it, we just created the equivalent of the Angular ngShow and Vue v-show Directives!

The last piece now, adding it to the Vue root instance in the main.ts file:

import Vue from "vue" ; import CustomShow from "./app/custom-show" ; var app = new Vue ( { el : "#app" , directives : { CustomShow } } ) ;

Ionic Vue Directives can be global too, just like this:

Vue . directive ( "CustomShow" , { bind : function ( el , binding , vnode ) { const display = binding . value ? "block" : "none" ; el . style . display = display ; } } ) ;

I personally prefer local Directives, but in some cases a global Directive might be useful.

Let's see another way for properties propagation.

This time we will pass an object in the index.html file:

< div id = " app " > < div v-custom-show = " { display: false, delay: 4000 } " > Custom Show </ div > </ div >

We spice up the custom-show.ts file:

export default { bind : function ( el , binding , vnode ) { const display = binding . value . display ? "block" : "none" ; const delay = binding . value . delay ; setTimeout ( ( ) = > ( el . style . display = display ) , delay ) ; } } ;

The binding's value property is now an object which has the display and delay properties.

This time, we will use the setTimeout method and make the DOM modification after the delay we received.

Here is the new result:

In Angular's terms, this is an Attribute Directives because:

It changes the appearance or behavior of an element, component, or another directive.

Let's move to a Structural Directive with the Custom If example.

Custom If Directive

Just like before, we start in the index.html file:

< div id = " app " > < div v-custom-if: 4000 :display = ' false ' > Custom If </ div > </ div >

The properties are propagated differently.

The display value is passed as an Element attribute and the delay is passed as a Vue Directive argument.

We will also change the way we declare our Ionic Vue Directive in a new custom-if.ts file:

import { Directive } from "vue-ts-decorate" ; @ Directive ( { name : "customIf" , local : true } ) export default class CustomIf { bind ( el , binding , vnode ) { const display = vnode . data . attrs . display ; const delay = binding . arg ; if ( display === false ) { setTimeout ( ( ) = > vnode . elm . remove ( ) , delay ) ; } } }

In a previous Ionic Vue Component tutorial, we used the vue-class-component library.

That's an awesome library, however, it only focuses on the Component Decorator.

This time, we will use the vue-ts-decorate library which has more Decorators so don't forget to:

npm i vue-ts-decorate --save

Ok, back to our Directive.

The Directive Decorator only needs the name of the directive. I've set the local value to true in order to make the Ionic Vue Directive local.

Just like an Angular Directive, we have the traditional export default ...

The bind function is declared with its el, binding and vnode arguments.

The display value is located in the vnode.data.attrs.display property.

binding is used once again, however, instead of looking for the information in the value property, we head to the arg property.

Both of those values are stocked in a display and delay const.

We then check if we should display the <div> Element.

Just like before we use a setTimeout, but this time the process is different.

The Angular ngIf and Vue v-if don’t hide the content by modifying the Element’s style.

They destroy and recreate the DOM Element, that’s why they are called Structural Directives.

We will be simple here and only use the vnode’s elm property’s remove method to destroy our Element.

We don’t forget to add the Directive to the Ionic Vue root Instance in the main.ts file:

import Vue from "vue" ; import CustomIfModule from "./app/custom-if" ; const CustomIf = CustomIfModule [ "custom-if" ] ; var app = new Vue ( { el : "#app" , directives : { CustomIf } } ) ;

The vue-ts-decorate library has its own format, and returns the Vue Directive in the custom-if property (our Directive name) so we need to do some gymnastic here.

Here is the final result:

Conclusion

Vue has two types of Directives: Attribute (ex: v-show) and Structural (ex: v-if).

Angular has one more: the Components which are Directives with templates.

There are many ways to pass information to an Ionic Vue Directive, it can be through binding’s value, arg or vnode.

As soon as we use TypeScript libraries like vue-class-component or vue-ts-decorate, Vue and Angular Directives become very similar, however, they both have their own LifeCycle and Hooks where the work happens, but that’s for another tutorial.