skip to Main Content

I’ve built the following directive to transform an input’s v-model into uppercase:

app.directive('uppercase', (el) => {
  el.value = el.value.toUpperCase()
})

But when I apply it, the resulting v-model returns the input value with the last character in lowercase.

  <template>
    <div>
      <input type="text" v-uppercase v-model="testInput" />
      <div>
        {{ testInput }}
      </div>
    </div>
  </template>
    
  <script setup>
    import { ref } from 'vue'
    const testInput = ref('')
  </script>

Why is this not working?

2

Answers


  1. Faced with a similar one. Not sure if this is the right solution, but I called the input event to work correctly:

    app.directive('uppercase', el => {
      el.value = el.value.toUpperCase();
      el.addEventListener('input', ($event: Event) => {
        if ($event.isTrusted) {
          el.value = el.value.toUpperCase();
          el.dispatchEvent(new Event('input'));
        }
      });
    });
    
    Login or Signup to reply.
  2. This isn’t a good use for a directive because it’s model value that is supposed to be the source of truth, not input value.

    Even if it’s possible to work around input value updates, as another answer shows, the mentioned problem would reveal because the directive won’t affect initial model value; the input wasn’t touched.

    A more straightforward approach is to address it from the side of a model:

    const testInput = ref('');
    
    watchEffect(
      () => { testInput.value = testInput.value.toUpperCase(); },
      { flush: 'sync' },
    );
    

    v-model modifiers are intended for this kind of modified behaviour. As shown in the documentation, custom component can implement a modifier similar to uppercase transform.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search