[Vuejs]-How to apply Vue directives to Vuetify custom components

0👍

You are applying the directive to your custom component InputTextField, not directly to Vuetify’s v-text-field so the statement I have found that the vuetify components don’t have the value property is not correct. Yours component doesn’t have a value property. v-text-field does as it supports v-model

But it does not matter here much. Problem is that Vue directives are pretty low level. From the docs:

Note that in Vue 2.0, the primary form of code reuse and abstraction is components – however there may be cases where you need some low-level DOM access on plain elements, and this is where custom directives would still be useful.

So directives operates directly on the DOM level, not on component level. el passed into directive hooks is not a component instance, it is always DOM element generated when the component is rendered. This is now properly documented in Vue 3 docs

So your directive (taken probably from this SO answer) will not work. One solution can be based on the other answer – Custom directive v-focus is not working on vuetify component – but it makes some assumptions on how the Vuetify component is rendered. Also check this forum thread for complications and other solutions…

Personally I would not go the directive route and stick to the advise given by Vue authors – the primary form of code reuse and abstraction is components

Note: I really don’t like the interface of your InputTextField custom input. Input handling in Vue is based on v-model and other devs (in your team) are used to it. Why make your custom input (essentially a wrapper) different?

You already have a custom component InputTextField so it should be easy to add simple boolean prop, for example uppercase and use it together with computed based v-model implementation like this:

Vue.component('custom-input', {
  props: {
    value: {
      type: String,
      required: true
    }, 
    uppercase: {
      type: Boolean,
      default: false
    }
  },
  template: `<input type="text" v-model="model">`,
  computed: {
    model: {
      get() { return this.value },
      set(newVal) {
        this.$emit('input', this.uppercase ? newVal.toUpperCase() : newVal)
      }
    }
  },
  watch: {
    value: {
      // to handle the situation when model value set by parent is not uppercase
      handler: function(newValue) {
        if(this.uppercase && newValue !== newValue.toUpperCase())
          this.model = newValue
      },
      immediate: true
    }
  }
})

new Vue({
  el: "#app",
  data() {
    return {
      text: "Hello"
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
  <custom-input v-model="text" :uppercase="true"></custom-input>
  <pre>{{ text }}</pre>
</div>

When upgrading to Vue 3 you can get rid of standalone props as uppercase and easily rewrite your component to use custom v-model modifiers

Leave a comment