Vuetify v-text-filedで数値のmax, minを設定する方法

# はじめに

Vuetifyのv-text-filedで最大値、最小値の2つを下記のようなルールで入力させたいときの方法です。
いろいろな実現方法あると思いますが、一つの方法として参考になればと思います。

**注意：最大値、最小値の上限下限が決まっている場合に有効な方法です。（だと思います）**

入力制限ルール：

- 最大値入力欄には、最小値未満の値を入れられない
- 最小値入力欄には、最大値未満の値を入れられない

イメージ

- 初期状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/e760ee26-7b4a-e06c-9077-daf979803521.png)

- 最小値のみ入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/821bf1bf-f4bd-a7e0-6139-bb0de2edc9f3.png)




- 最大値のみ入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/06e7f7a0-e4d7-8b33-360b-bd0e749d74bc.png)



- ルール違反時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191958/e2f6204f-4018-8c4b-4a1e-77bdd2be57c0.png)




# コード

```vuejs
<template>
  <v-row align="center">
    <v-col cols="5">
      <v-text-field
        class="inputValue"
        v-model.number="inputMin"
        :rules="[rules.min(inputMax, inputMin)]"
        label="数値を入力"
        type="number"
        @focusout="focusout('min')"
      />
    </v-col>
    <v-col cols="2" class="text-center"><span>～</span></v-col>
    <v-col cols="5">
      <v-text-field
        class="inputValue"
        v-model.number="inputMax"
        :rules="[rules.max(inputMin, inputMax)]"
        label="数値を入力"
        type="number"
        @focusout="focusout('max')"
      />
    </v-col>
  </v-row>
</template>

<script>
  export default {

    components: {
    },

    props: [
    ],

    data () {
      return {
        inputMin: null,
        inputMax: null,

        INPUT_MIN_VALUE: 0,
        INPUT_MAX_VALUE: 10000,
        rules: {
          min: (max, v) => {
            const _max = max === null? this.INPUT_MAX_VALUE: max // maxが未設定(null)の場合は適当に大きな数字を設定可能な最大値に設定
            return v <= _max || `最大値 よりも小さい値を設定してください`;
          },

          max: (min, v) => {
            if (v === null) return true // 最大値未入力の場合そのままtrueを返す
            const _min = min === null? this.INPUT_MIN_VALUE: min // minが未設定(null)の場合は0を設定可能な最小値に設定
            return v >= _min || `最小値 よりも大きい値を設定してください`;
          }
        }
      }
    },

    computed: {
    },

    watch: {
    },

    methods: {
      focusout (type) {
        // v-text-filedはフォーカスを当てて、何も入力しないでフォーカスを外すと空文字("")がv-modelの中に入るので、その対応
        // (もっとスマートなロジックにしたい)
        const targetVal = type === 'min'? this.inputMin: this.inputMax
        if ((typeof targetVal) === 'string') {
          switch(type) {
            case 'min':
              this.inputMin = null
              break
            case 'max':
              this.inputMax = null
              break
            default
              break
          }
        }
      }
    }
  }
</script>

<style scoped>
.inputValue >>> input[type="number"] {
  -moz-appearance: textfield;
}
.inputValue >>> input::-webkit-outer-spin-button,
.inputValue >>> input::-webkit-inner-spin-button {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
}
</style>
```

## おわりに
ある程度のテストはしていますが、簡単に作ったものなので、入力パターンによっては不具合があるかもしれません。

## 参考
- https://stackoverflow.com/questions/56835707/min-max-validation-vuetify
- https://stackoverflow.com/questions/66531177/is-there-a-way-to-remove-the-arrows-from-an-input-type-but-keeping-it-scoped-to