Making a custom vuejs directive

damilola jolayemi
Damilola Jolayemi
Published in
4 min readNov 12, 2017

A vue directive is a function that can be attached to DOM elements to make them do certain things. They are most useful at those times when you need low-level access to an element, maybe to customize the behavior or look. If you want to give directions to an element, Vue custom directives is way to go.

You have been using the default directives provided by Vue e.g v-model, v-if, v-on, etc. When you need to add a little customization to certain elements and a component will be an overkill, a directive is what you should go for. Let’s build one.

We would make a directive that changes the border-color of an element based on the value we pass in. If it’s greater than or equal to 12 we would change it to red. If not, we do nothing to it. Use case for this directive can be in an application where you need to specify temperature, the color change can be used to represent hot or cold. Let’s begin.

<div id="app" class="container">
<div class="box" v-estimate="23">
<p class="message">Lorem ipsum dolor sit amet, consectetur</p> </div> <div class="box" v-estimate="5"> <p class="message">Lorem ipsum dolor sit amet, consectetur</p> </div></div

In the code above we have a custom directive v-estimate attached to a div element, it’s set equal to 23 and we are going to make it perform the action described above, in the third paragraph. All directives should be prefixed with v- .

A directive can be as simple as v-estimate You don’t have to set it equal to anything, but in this case we do need to because this directive needs to perform an action based on the value we are passing in.

Next, in your vue root instance, add the code below, it will create a global directive called estimate that any component can use.

Vue.directive(‘estimate’, {})

The vue.directive() method takes in the directive name (estimate) as first parameter and also an object as the second parameter. Inside the object is where we specify the functionality of directives i.e determine what it will do.

Before going any further, we need to understand that like components which have life cycle hooks (mounted, destroyed, created etc.). Vue directives do too, five in total.

  • bind: called only once, when the directive is first bound to the element.
  • inserted: called when the bound element has been inserted into its parent node.
  • update: called after the containing component’s VNode has updated, but possibly before its children have updated.
  • others are componentUpdated and unbind. Read more

The hook we would be using here is bind because we want our code to run as soon as the directive is bound to the div element on our page. In the object ie. second parameter, put in a bind function.

Vue.directive(‘estimate’, {
bind() {
}})

The bind hook as well as the other hooks can be passed arguments. The list of arguments you can pass includes:

  1. el(The element the directive is bound to, this is used to manipulate the DOM.), binding, vnode and oldVnode.

2. binding is an object that contains information about the directive. It’s properties includes:

  • name: The directive name, without the v- prefix.
  • value: The value passed to the directive. For example in our directive, the value is 23.
  • others include oldValue, expression, arg and modifiers. Read more

3. vnode: The element’s virtual node created by Vue’s compiler. Read more

4. oldVnode: The element’s previous virtual node.

The hook you call determines the arguments you are required to pass in to it.

bind(el, binding, vnode)inserted(el, binding, vnode)update(el, binding, vnode, oldVnode)componentUpdated(el, binding, vnode, oldVnode)unbind(el, binding, vnode)

In our directive we need to get the value passed in so we can style the element’s border color if the the time is over 12 hours old. This is how we do that:

Vue.directive(‘estimate’, {
bind(el, binding, vnode) {
if(binding.value >= 12) {
el.style.borderColor = "red"
}
}})

In the code above, after checking if the value is greater than or equal to 12, we get the element’s css style property, choose the border-color property, since it’s what we need, finally, we set the borderColor(when two words are used it should be carmelCase) property to equal to red. Done!

Our vue directive is complete. I have put this on a fiddle, access it here.

Arguments

You know like in the default directives provided by vuejs e.g

v-on:click="doStuff" or v-on:whateverIsHere="doStuff"

The word after colon : is the directive argument. In the line above, the click and whateverIsHere are the directive arguments. You can add this to custom directives too. Let’s add an argument to our directive to make it ignore some div elements.

<div id="app" class="container">
<div class="box" v-estimate="23">
<p class="message">Lorem ipsum dolor sit amet, consectetur</p> </div> <div class="box" v-estimate="5"> <p class="message">Lorem ipsum dolor sit amet, consectetur</p> </div>
<div class="box" v-estimate:ignore="1000">
<p class="message">Lorem ipsum dolor sit amet, consectetur</p> </div></div

The argument passed in can be accessed by doing binding.arg. arg is one of the bound element’s binding properties. To access the argument on our directive we do this:

Vue.directive(‘estimate’, {
bind(el, binding, vnode) {
if(binding.value >= 12 && !binding.arg) {
el.style.borderColor = "red"
}
}});

Now if you attached our directive to an element and you include the ignore argument in the directive, the element will be ignored.

Common Error

When you pass in a value to the directive and you get this error:

Property or method name “value-you-passed-in” is not defined on the instance but referenced during render…

It’s most likely because you want to pass in a string so you did this:

<div v-estimate="value-you-passed-in"></div>

Do this instead:

<div v-estimate=" 'value-you-passed-in' "></div>

Thank you for reading.

--

--