Subscribe on changes!

input type=number doesn't work as intended

avatar
May 21st 2021

Version

3.0.11

Reproduction link

https://jsfiddle.net/4ou5ghLd/18/

Steps to reproduce

Vue tries to automatically apply a number modifier to v-model that are set on input[type=number], as can be seen in the code here: https://github.com/vuejs/vue-next/blob/master/packages/runtime-dom/src/directives/vModel.ts#L52

Go to the repro link, try to enter a number in the textbox, you'll see the model contains a string, not a number

What is expected?

v-model set the ref to a number when used on input[type=number]

What is actually happening?

v-model sets the ref to a string, even if the number is valid


I put a breakpoint inside Vue and it seems like the source line linked above ran before other input properties are set. The className is still empty and the type is still text (the default input type).

I recall a change was made on when v-model is applied to input vs other attributes because of an issue related to min and max, this could be a regression introduced by that change.

avatar
May 22nd 2021

Where is this behaviour described in docs? I can't find anything about it, neither in the guide/api reference nor in the migration guide.

avatar
May 22nd 2021

Where is this behavior described in docs?

There is no such thing, Vue2 also does not have this behavior. .number is recommended.

Maybe the PR I submitted is not needed because of the increased runtime overhead.

avatar
May 22nd 2021

Then maybe || el.type === 'number' could just be removed?

avatar
May 22nd 2021

@jacekkarczmarczyk I found out about this feature by reading the code. I don't think I ever saw it mentioned in docs.

I'd say it's rather logical and nice to have, when you bind a type=number you kind of expect its value to be a number, don't you? A bit like when you bind a type=checkbox you get a boolean.

A quick blame shows that the code was introduced by @yyx990803 in 3.0.0-alpha.0. The commit comment doesn't provide a lot of background:

feat(v-model): number/trim modifier + array checkbox support

Up to you what you want to do about it. If it's not intended to work that way you prob. should remove the code.

Although I said above that it's very convenient to automatically get a number out of type=number, it's a bit unique in that you don't get a Date out of type=date for example. That would be easy enough by reading valueAsDate but would certainly be a significant breaking change.

avatar
May 23rd 2021

Since this is an undocumented feature, I will not mark it as a bug, and @edison1105's PR can fix it, let’s wait for @yyx990803 ’s input.

avatar
May 27th 2021

It would be problematic to have the modifier applied implicitly to v model as there would be no way to turn it off and the string version is more flexible

avatar
Oct 13th 2021

@posva, @yyx990803

A general follow-up question. Can I somehow detect these things build-time? I got bitten of this since this typechecks and emits fine but the string is a number runtime:

<script setup lang="ts">

import { computed } from '@vue/reactivity';

const props = defineProps<{ modelValue: string }>()
const emit = defineEmits(['update:modelValue']);

const value = computed<string>({
    get() {
        return props.modelValue
    },
    set(val) {
        emit('update:modelValue', val);
    }
})
</script>

<template>
    <input type="number" v-model="value" />
</template>

But I guess that's the general case, not just for this string/number thing…?