diff --git a/packages/runtime-dom/__tests__/directives/vModel.spec.ts b/packages/runtime-dom/__tests__/directives/vModel.spec.ts index 33d48e5fc6c..2aa17a16767 100644 --- a/packages/runtime-dom/__tests__/directives/vModel.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vModel.spec.ts @@ -681,6 +681,43 @@ describe('vModel', () => { expect(bar.selected).toEqual(true) }) + it('v-model.number should work with select tag', async () => { + const component = defineComponent({ + data() { + return { value: null } + }, + render() { + return [ + withVModel( + h( + 'select', + { + value: null, + 'onUpdate:modelValue': setValue.bind(this) + }, + [h('option', { value: '1' }), h('option', { value: '2' })] + ), + this.value, + { + number: true + } + ) + ] + } + }) + render(h(component), root) + + const input = root.querySelector('select') + const one = root.querySelector('option[value="1"]') + const data = root._vnode.component.data + + one.selected = true + triggerEvent('change', input) + await nextTick() + expect(typeof data.value).toEqual('number') + expect(data.value).toEqual(1) + }) + it('should work with composition session', async () => { const component = defineComponent({ data() { diff --git a/packages/runtime-dom/src/directives/vModel.ts b/packages/runtime-dom/src/directives/vModel.ts index ea1098dd19b..d46491d0d73 100644 --- a/packages/runtime-dom/src/directives/vModel.ts +++ b/packages/runtime-dom/src/directives/vModel.ts @@ -166,12 +166,19 @@ export const vModelRadio: ModelDirective = { } export const vModelSelect: ModelDirective = { - created(el, binding, vnode) { + created(el, { modifiers: { number } }, vnode) { addEventListener(el, 'change', () => { + const castToNumber = number const selectedVal = Array.prototype.filter .call(el.options, (o: HTMLOptionElement) => o.selected) .map(getValue) - el._assign(el.multiple ? selectedVal : selectedVal[0]) + + let domValue: string | number = el.multiple ? selectedVal : selectedVal[0] + + if (castToNumber) { + domValue = toNumber(domValue) + } + el._assign(domValue) }) el._assign = getModelAssigner(vnode) },