DEV Community

Cover image for Vue.js custom directives with examples. ↘
Vaibhav Khulbe
Vaibhav Khulbe

Posted on

Vue.js custom directives with examples. ↘

After making some custom components, it's time to learn a bit about custom directives. There are some really helpful and awesome ones built-in Vue, but heck yes, we can create our own custom ones. This article will show you how to do this with examples.

Example GIF

Exactly this!

What are directives in Vue? 🤔

As per its documentation,

"A directive is some special token in the markup that tells the library to do some changes to a DOM element."

Let's make the above sentence better. You see, when we write HTML, we start with a tag (<h1>), then close it (</h1>). In between the tag, we add what we want to display (Hello World!) and when we want to add some styling to this, we use some attributes like style.

<h1 style="color: grey;">Hello World!</h1> 
Enter fullscreen mode Exit fullscreen mode

Something similar can be applied to Vue's template markup. A Vue.js directive can only appear in the form of a prefixed HTML attribute that takes the following format:

<div v-text="message"></div>
Enter fullscreen mode Exit fullscreen mode

In this case, v-text is a directive of the div element. Here are some other examples:

<!-- Example format with custom element -->
  prefix-directiveId="[argument:] expression [| filters...]">

<!-- Example with inline expressions -->
<div v-text="'hello ' + user.firstName + ' ' + user.lastName"></div>

<!-- Example with an argument -->
<div v-on="click : clickHandler"></div>
Enter fullscreen mode Exit fullscreen mode

Vue already got some nifty core directives like v-model and v-show, but it doesn't stop you to make custom ones!

How to make custom directives? 🧐

Before we make it, let's see its syntax or examples. There are two ways you can register them:

Registering globally: Want to make a custom directive which automatically focuses an input field when someone opens up your web app?

Vue.directive('custom-directive-name', {
  inserted: function (el) {
    // Add code to focus the input field
Enter fullscreen mode Exit fullscreen mode

Here's how we'll use the above directive in our app template:

<app-input custom-directive-name></app-input>
Enter fullscreen mode Exit fullscreen mode

Let's break-down the new things you see above:

  • The Vue.directive is used to register or retrieve a global directive.

  • The inserted is a Hook function which is called when the element to bound has been 'inserted' into its parent node.

Hook functions are some of the default (but optional) functions provided by Vue over directives. The one hook function in which we are interested in is the bind function. It's called when the directive is first bound to the element.

Each of these functions has three additional arguments:

  • el: the 'element' on which the binding sits.
  • binding: the object which contains the arguments that are passed into the hooks.
  • vnode: this allows us to directly refer the virtual DOM.

Registering locally: If one of your components needs a custom directive then you can seamlessly register it under the <script> tag (for local) or inside your main.js (for global) file as follows:

directives: {
  custom-directive-name: {
    // directive definition
    inserted: function (el) {
      // Add code for the directive
Enter fullscreen mode Exit fullscreen mode

Okay, let's get serious and build one from scratch. For demo purposes, we'll make a custom directive which simply changes the text colour of a heading.

Step 1: Register the global directive

Open up the main.js file in your newly created Vue project. Start by declaring the custom directive. Note that you should define all of your global directives before the Vue's instance creation code.

Let's name our custom directive as colorChange. Inside this, we'll access the provided bind hook function passing in both the el and binding arguments.

Vue.directive("colorChange", {
  bind(el, binding) {
    // Code to change the text color dynamically 
Enter fullscreen mode Exit fullscreen mode

So, how do we change the color? Here, both the el and binding arguments come into play. We pick the element we want to change using el, over it we set the style property to be color through which we change color in CSS. Then, we set this value to be equal to the value stored in the binding i.e our element!

Now, our code updates like this:

Vue.directive("colorChange", {
  bind(el, binding) { = binding.value;
Enter fullscreen mode Exit fullscreen mode

Step 2: Use the new directive

Open any of your component where you need this functionality, where there is a heading (<h1>) or just a text (<p>) in the template, simply add the newly created colorChange custom directive. Pass in any color value in the String format.

Note that all custom/local directives in Vue start with v-. Here's an example of how to use this:

    <h1>Custom Directives</h1>

    <h1 v-colorChange="'red'">
    This is a custom directive RED text</h1>

    <h2 v-colorChange="'#f2652f'">
    This is a custom directive TOMATO text</h2>

    <p v-colorChange="'dodgerblue'">
    This is a custom directive DODGERBLUE text</p>
Enter fullscreen mode Exit fullscreen mode

Notice how you can pass both the CSS color names and the hex values also!

This is what you’ll see in the output window:

Custom directive output

Where to next? 🤔

Make the above directive more powerful by adding an option for the user to manually choose a color or play with other properties provided by Vue. The following resources might help:

Thanks for reading, I appreciate it! Have a good day. (✿◕‿◕✿)

*looks in library* yup, this is the @MicrosoftLearn course you'll want:

Image source: #Python #Developer

— Microsoft Developer UK (@msdevUK) September 14, 2020

📫 Subscribe to my weekly developer newsletter 📫

PS: From this year, I've decided to write here on DEV Community. Previously, I wrote on Medium. If anyone wants to take a look at my articles, here's my Medium profile.

Top comments (2)

phillt profile image

So custom direcitves only work on DOM elements, but not on components?

vaibhavkhulbe profile image
Vaibhav Khulbe

They do work on components. Check this in docs.