3
0
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

【Nuxt・Vue】フォーカスで数値、フォーカスアウトでカンマ付き数値のテキストフィールド

Posted at

はじめに

金額系のテキストフィールドを実装する際に以下のようなUI仕様にしたいってありますよね。

  1. 通常は「100,000」のように3桁でカンマ区切りで数値をテキストフィールドに表示したい
  2. マウスやTABキーなどでテキストフィールドにカーソルが当たったら「100000」と普通の数値の編集ができる
  3. カーソルがテキストフィールドから外れたら再び「100,000」の表示になる

今回はVue(Nuxt)でこの機能を実装したテキストフィールドコンポーネントのサンプルコードを紹介します。

これはプロトタイプです。
最低限の機能のみなので、要件に応じてここからpropsなどを追加してアレンジしてくださいね!

デモ

App.vue
<template>
  <div>
    <TextField v-model="input" />
    <p>親側で取得している値: {{ input }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import TextField from "@/components/TextField.vue";

const input = ref<string>("100000000");
</script>

テキストフィールドの下にはコンポーネントからv-modelで取得した値を表示しています。
デモでは初期値を入れています。

テキストフィールドコンポーネント

template 部分

今回はかなりシンプルなパターンを想定しています。必要に応じて拡張してください。

TextField.vue
<template>
  <input
    class="TextField"
    type="text"
    :value="inputValue"
    @input="handleInput"
    @blur="handleBlur"
    @focus="handleFocus"
  />
</template>

使うメソッドのざっくりとした役割は以下です。

イベント メソッド 説明
input handleInput 入力された文字を取得する
focus handleFocus カンマ付き数値を通常の数値にする
blur handleBlur 数値をカンマ区切りにする

script 部分

基本仕様の定義

TextField.vue
import { ref, onMounted } from "vue";
interface Props {
  modelValue?: string;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: "",
});

const emit = defineEmits(["update:modelValue"]);

// 入力値
const inputValue = ref(props.modelValue);

propsは一旦親側でv-modelで取得するためにmodelValueを定義します。
言い換えると、テキストフィールドに入力したテキストはmodelValueに入ります。

inputValueは、コンポーネント側でmodelValueのテキストにカンマをつけたりとったりした値を入れる上書き用の、いわばmodelValueのコピーのようなイメージです。

propsのmodelValueを直接コンポーネント側で書き換えることは避けるべきなので、上書き用のinputValueを用意します。

メソッド

TextField.vue
// 入力値(数値)をカンマ区切りに変換
const addComma = () => {
  if (props.modelValue.length) {
    const numModelValue = Number(props.modelValue);
    inputValue.value = isNaN(numModelValue)
      ? props.modelValue
      : numModelValue.toLocaleString();
  }
};

// フォーカス外
const handleBlur = () => {
  addComma();
};

// フォーカス
const handleFocus = () => {
  inputValue.value = props.modelValue;
};

// 入力値
const handleInput = (event: Event) => {
  inputValue.value = event.target.value;
  emit("update:modelValue", inputValue.value);
};

onMounted(() => {
  addComma(); // 初期表示時にカンマ区切りに変換
});

書くメソッドの役割は以下です。

メソッド 説明
addComma modelValueに値が入っている、かつ数値だった場合にカンマを付与する
handleBlur フォーカスが外れた時にカンマをつける
handleFocus フォーカスが当たった時にmodelValueの値を表示する
handleInput 入力値をイベントで伝播する
onMounted 初期レンダリング後に数値が既に入っていた場合のカンマ表示

ポイント

デモを操作していただくと分かると思いますが、テキストフィールドのvalueはカンマをつけたりとったりしていますが、v-modelで親側から取得した値はフォーカスの有無で変化はありません。

「カンマの表示・非表示」というのはあくまで視覚的な要件のお話なので、データを扱う場合にはカンマは不要なケースが多いため、v-modelで取得した値には影響しない仕様にしています。

おわりに

金額系を扱う時に割とあるあるな要件なので、形はすぐ作れるようにしておきたいですね:v:

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0