Vue3: How to prevent further input when value meets a certain condition

Viewed 214

I'm primarily a React developer but I'm dipping my toes back into Vue again.

I'm making an app which allows you to convert your running pace between minutes per km and minutes per mile. The minute and second values for each unit are set in a parent component and passed down into child input components. I would like to prevent users from entering values higher than 59 into the number inputs but the v-model functionality continues to allow users to type beyond that.

I'm probably approaching this from a React mindset, so any help would be greatly appreciated!

App.vue

<template>
    <div>
        <NumberInput
            :id="'kmMins'"
            :unit="'km'"
            v-model="kmMins"
        />
    </div>
</template>

<script>
    import NumberInput from "./NumberInput.vue";
    export default {
        name: "App",
        data() {
            return {
                kmMins: 0,
            }
        },
        components: {
            NumberInput
        }
    }
</script>

NumberInput.vue

<template>
    <input
        type="number"
        placeholder="00"
        :value="modelValue"
        @input="$emit('update:modelValue', sanitize($event))"
    />
</template>

<script>
    export default {
        name: "NumberInput",
        props: ['id', 'unit', 'modelValue'],
        methods: {
            sanitize(e) {
                const { value } = e.target;
                if (!Number.isNaN(value) && value < 60) {
                    return value;
                }
                return this.modelValue;
            }
        }
    }
</script>
2 Answers

App.vue

<template>
    <div>
        <NumberInput
            :id="'kmMins'"
            :unit="'km'"
            v-model="kmMins"
        />
    </div>
</template>

<script>
    import NumberInput from "./NumberInput.vue";
    export default {
        name: "App",
        data() {
            return {
                kmMins: 0,
            }
        },
        components: {
            NumberInput
        },
        watch: {
            kmMins(newValue, oldValue){
                 if(newValue > 59){
                    this.kmMins = 59
                 }
            }
        }
    }
</script>

Have you considered using watch? I haven't tested it but I think this will work. If it works you can deal with it for now.

<template>
    <input
        type="number"
        placeholder="00"
        v-model= "checkNumber"
    />
</template>

<script>
        export default {
        name: "NumberInput",
        props: ['id', 'unit', 'modelValue'],
        data(){
return{
    checkNumber : 0,
}
        },
        watch:{
            checkNumber(val){
                if(val<5){
                    $emit('update:modelValue', sanitize($event))
                }else{
                    console.log(">>> value greater then 5" , val)
                }
            }
        },
        methods: {
            sanitize(e) {
                const { value } = e.target;
                if (!Number.isNaN(value) && value < 60) {
                    return value;
                }
                return this.modelValue;
            }
        }
    }
</script>

in the above code i have used watch which is like useEffect in react this will watch the variable change in every change like onChange function in react. And if the data if greater then 5 it will send error . else data will be send back to your parent div.

Related