Custom Directive in nuxt js
Asked Answered
B

5

23

is there a way how to write a custom directive in nuxt js, which will work for ssr and also for frontend (or even for ssr only)?

I tried it like in following documentation: https://nuxtjs.org/api/configuration-render#bundleRenderer

so I added this code:

  module.exports = {
      render: {
        bundleRenderer: {
          directives: {
            custom1: function (el, dir) {
              // something ...
            }
          }
        }
      }
    }

to nuxt.config.js

then I use it in template as:

<component v-custom1></component>

but it doesn't work, it just throw the frontend error

[Vue warn]: Failed to resolve directive: custom1

And it doesn't seem to be working even on server side.

Thanks for any advice.

Brumley answered 17/7, 2018 at 15:51 Comment(2)
thanks @Sphinx, but that's in general the same code as I pasted and it doesn't work for me, don't you have some working example please?Hazy
I met the same problem as yours now (Nuxt.js 1.4.0). I just tried bundleRenderer.shouldPreload it works fine, but bundleRenderer.directives didn't.Alida
I
6

Tested in nuxt-edge ( its nuxt 2.0 that will be out in this or next month, but its pretty stable as it is).

nuxt.config.js

  render: {
    bundleRenderer: {
      directives: {
        cww: function (vnode, dir) {
          const style = vnode.data.style || (vnode.data.style = {})
          style.backgroundColor = '#ff0016'
        }
      }
    }
  }

page.vue

<div v-cww>X</div>

Resulting html from server:

<div style="background-color:#ff0016;">X</div>
Isle answered 25/7, 2018 at 17:46 Comment(4)
How would you set innerText of the element?Moffit
@TimarIvoBatis Try this one, #59402283Wilhelmstrasse
Thanks haha that was my question and also my answer :DMoffit
PS: I've also did a small write up on custom SSR directives: blog.lichter.io/posts/universal-ssr-vue-component-guide/…Lebrun
K
28

If you want use custom directives in Nuxt you can do the following:

  • Create a file inside plugins folder, for example, directives.js
  • In nuxt.config.js add something like plugins: ['~/plugins/directives.js']

In your new file add your custom directive like this:

import Vue from 'vue'

Vue.directive('focus', {
  inserted: (el) => {
    el.focus()
  }
})
Knee answered 17/7, 2018 at 16:19 Comment(2)
thanks for a hint, but this works only on frontend, it doesn't have any effect on server side rendered html.Hazy
Worked by using bind and unbind in this syntax.Macerate
G
13

How To Create A Directive


You can make directives run on the client by adding the .client.js extension to your directives file. This works for SSR and static rendering.

// plugins/directive.client.js

import Vue from 'vue'

Vue.directive('log-inner-text', {
  inserted: el => {
    console.log(el.innerText)
  }
})

How To Insert Directives

In your nuxt.config.js file add it as a plugin like this.

plugins: [
  '~/plugins/directive.client.js'
]

Don't forget to save your directive in the plugins folder.


How To Use A Directive

<div v-log-inner-text>Hello</div>

Console logs

> "Hello"

I have written a medium article that goes a lot more in-depth on how this works. It shows you how to make a directive that makes an element animate into view on scroll: Nuxt - Creating Custom Directives For Static & SSR Sites

Gipps answered 18/8, 2020 at 13:47 Comment(0)
I
6

Tested in nuxt-edge ( its nuxt 2.0 that will be out in this or next month, but its pretty stable as it is).

nuxt.config.js

  render: {
    bundleRenderer: {
      directives: {
        cww: function (vnode, dir) {
          const style = vnode.data.style || (vnode.data.style = {})
          style.backgroundColor = '#ff0016'
        }
      }
    }
  }

page.vue

<div v-cww>X</div>

Resulting html from server:

<div style="background-color:#ff0016;">X</div>
Isle answered 25/7, 2018 at 17:46 Comment(4)
How would you set innerText of the element?Moffit
@TimarIvoBatis Try this one, #59402283Wilhelmstrasse
Thanks haha that was my question and also my answer :DMoffit
PS: I've also did a small write up on custom SSR directives: blog.lichter.io/posts/universal-ssr-vue-component-guide/…Lebrun
R
1

For anyone else coming here, the accepted answer allows you to run an SSR-only directive. This is helpful but a little unintuitive if you want to have a directive run everywhere.

If you only use nuxt.config.js to implement a directive via render, it will not be supported on the client-side without also adding a directive plugin and adding it to the config (see the How to Create a Directive Answer).

To test this out, try this experiment:

  • Follow the instructions to create directive using plugins (make one called loading)
Vue.directive('loading', function (el, binding) {
  console.log('running loading directive client side')
})
  • Add this to your nuxt.config:
  render: {
    bundleRenderer: {
      directives: {
        loading (element, binding) {
          console.log('running loading directive server side')
        }
      }
    }
  }

Use the directive on a Vue page file like:

<div v-loading="true">Test</div>

On page load, you will see both the client-side and SSR directives run. And if you remove the client-side directive, you will see errors thrown like the OP had: [Vue warn]: Failed to resolve directive: loading.

Tested on nuxt 2.12.2.

Runofthemine answered 5/2, 2021 at 0:15 Comment(0)
D
1

In Nuxt 3 - You should do it like this:

// plugins/directive.ts
export default defineNuxtPlugin((nuxtApp) => {
    nuxtApp.vueApp.directive('my-directive', {
        mounted(element, binding, globalThis) {
            // Your custom directive logic here
            console.log("My directive works!", binding.value); // Output: the value passed as an argument to the directive. In this case the string 'Hello'
        }
    });
});

and you can use like this:

<my-component v-my-directive="'Hello'">
Dryly answered 4/6 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.