write number within a range in input text

36 views Asked by At

I have two text inputs which are linked by their v-model to a ref that is an object, I have two more refs: minimum(100) and maximum(1000) which I am looking for is to be able to write in these inputs between the range of minimum and maximum, but if the value that I write is less than the minimum, it will automatically show the minimum value (100), if it is greater than the maximum, it will show the maximum.

<input type="text" v-model="number.one" class="one" @input="validate"/> 
<input type="text" v-model="number.two" class="two" @input="validate"/>

const min = ref(100)
const max = ref(1000)

const numbers = ref({
   one: 100,
   two: 100
}) 

const validate = () => {
    if(e.target.className === 'one'){
      if(numbers.value.one <= min.value){
         numbers.value.one = min.value
      }else if(numbers.value.one > max.value){
         numbers.value.one = max.value
      }
    }
}


I do this, but from here it no longer lets me write anything in the input, I think I know it's because numbers.value.one is now equal to the minimum so I can't modify it anymore, but how can I change the amounts?

1

There are 1 answers

3
Raeisi On

Checking min & max values for inputs can be easily achieved by tuning their HTML props. There is no need for extra validation.

<template>
  <input type="number" v-model="numbers.two" :max="max"/>
  <input type="number" v-model="numbers.one" :min="min"/>
</template>

<script setup lang="js">

import { reactive, ref } from 'vue';

const min = ref(100);
const max = ref(1000);

const numbers = reactive({
  one: 100,
  two: 100,
});
</script>

However, if you persist in checking every change's values, you need to validate ranges on input or change events.

<template>
  <input type="text" v-model="numbers.one" class="one" @input="validateMax"/>
  <input type="text" v-model="numbers.two" class="two" @change="validateMin"/>
  <!--  <input type="text" v-model="numbers.two" class="two" @input="validateMin"/>-->
</template>

<script setup lang="js">

import { reactive, ref } from 'vue';

const min = ref(100);
const max = ref(1000);

const numbers = reactive({
  one: 100,
  two: 100,
});

function validateMax() {
  numbers.one = Math.min(Number(numbers.one), max.value);
}

function validateMin() {
  numbers.two = Math.max(Number(numbers.two) || 0, min.value);
}

</script>

Here, on every change, new values are validated against min and max values, and the model gets updated.

There are some edge cases that must be addressed. Checking the min value on every input event breaks the user interface. As your min value is 100, when a number like 250 is going to be entered, at the very first step, the validation event is triggered by 2 and the value will be converted to 100. So, in practice, you cannot use the input event here. The change event must be used.

Note 1 It is a good practice to use v-model.number for numeric bindings.

Note 2 It also is a good practice to use type="number" for numeric inputs.