株式会社HAMWORKS
🖌

Vuetify + maska 導入

2024/04/29に公開

Vue 2 のときは inputmask-core を使っていましたが、Vue 3 になってからは maska を使うことにしました。
理由としてはアップデートがあまり行われておらず、アップデートのタイミングで maska を使うことにしました。

https://www.npmjs.com/package/inputmask-core

https://beholdr.github.io/maska/#/

maska は、 単独・Vue・Nuxt 3にも対応しているライブラリです。
今回は、Vuetifyの v-text-field に maska を導入する方法を紹介します。

maska の導入

ドキュメントの通り npm でインストールしていきます。

npm i maska

CDN や ES modulesでも利用できます。
マスクをかける場合は、以下のように設定することで利用できます。

<script setup>
import { vMaska } from "maska"
</script>

<template>
  <input v-maska data-maska="#-#">
</template>

data-maska に #-# と設定することで 数字のトークンを設定できます。
トークンのパターンは、以下の通りです。

https://beholdr.github.io/maska/#/?id=tokens

{
  '#': { pattern: /[0-9]/ },       // digits
  '@': { pattern: /[a-zA-Z]/ },    // letters
  '*': { pattern: /[a-zA-Z0-9]/ }, // letters & digits
}

Nuxt 3の場合は、 pluginsに設定するとグローバルで v-maska を利用することができます。
今回はstorybookの利用前提になりますので、コンポーネントから呼び出すようにしました。

// Nuxt でグローバルで v-maska を利用する場合
import { vMaska } from "maska"

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.directive("maska", vMaska)
})

vMaska用のコンポーネントを利用できるように、vMaskaをインストールして propsにMaskパターンを渡せるようにします。
maskのパターンを v-maskにわたす場合は、 v-maska:[options] で options で設定します。

Vuetifyの v-text-field に設定していきます。

<v-text-field v-maska:[options]></v-text-field> を設定することでpropsに定義した マスクを定義できます。

setValueには、一時的にrefに値を定義しておき、emitsで設定した値を update:modelValue で親のコンポーネントに渡すようにします。

<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from 'maska'
const props = withDefaults(defineProps<{
  modelValue: string
  maskPattern: string
}>(), {
  modelValue: '',
  maskPattern: '#-#'  // defaultは 数字のみ
})

const setValue = ref(props.modelValue)

const options = {
  mask: props.maskPattern
}

const emits = defineEmits<{
  'update:modelValue': [modelValue: string]
}>()

const onValueChange = (value: string) => {
  setValue.value = value
  emits('update:modelValue', setValue.value)
}
</script>

<template>
  <div>
    <v-text-field v-maska:[options] :model-value="setValue" @update:model-value="onValueChange" />
  </div>
</template>

今回の検証用のサンプルコードとstorybookは以下のURLになります。

https://nuxt3-vuetify-storybook.pages.dev/?path=/docs/components-vmasktextfield--documentation

https://github.com/redamoon/nuxt3-vuetify-storybook/blob/main/components/VMaskTextField/VMaskTextField.vue

数字のみ

maskPattern: '####' と設定して、よくあるパスコードのような数字を入力するフィールドを作れます。

日付

maskPattern: '####-##-##' と設定して、日付を入力するフィールドを作れます。
ここでは、現在の日付以上の入力バリデーションを加えてみました。

繰り返し日付

maskPattern: '####-##-## ~ ####-##-##' と設定して、期間を設定できるようなフィールドを作ることができます。

繰り返し日時:時間

maskPattern: '####-##-## ##:## ~ ####-##-## ##:##' と設定して、期間に加えて時間を設定したフィールドを作成することができます。

電話番号

maskPattern: '###-####-####' と設定して、電話番号を入力するフィールドを作成することができます。

まとめ

maskaを利用してVuetifyのコンポーネントと組み合わせた紹介でした。
この手のマスク系ライブラリはいくつかありますが、 v-maskaはVue3やNuxt3にも対応しており導入も簡単でした。
maskaで行えるトークンパターンにマッチする場合は、このライブラリを利用した形でバリデーションの対応範囲を限定的にすることができます。

もし使うケースが出た場合は v-maskaを検討してみても良いかもしれません。

株式会社HAMWORKS
株式会社HAMWORKS

Discussion