]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): v-model should support number modifier with select tag (#2308)
authoredison <daiwei521@126.com>
Wed, 7 Oct 2020 19:06:41 +0000 (03:06 +0800)
committerGitHub <noreply@github.com>
Wed, 7 Oct 2020 19:06:41 +0000 (15:06 -0400)
close #2252

packages/runtime-dom/__tests__/directives/vModel.spec.ts
packages/runtime-dom/src/directives/vModel.ts

index 33d48e5fc6cb6fba64f005e11947be5d4e752a71..140ef08d8cdd59cfdf3e0c71e5e3c1c50e205b77 100644 (file)
@@ -681,6 +681,108 @@ 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('v-model.number should work with multiple select', async () => {
+    const component = defineComponent({
+      data() {
+        return { value: [] }
+      },
+      render() {
+        return [
+          withVModel(
+            h(
+              'select',
+              {
+                value: null,
+                multiple: true,
+                '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 two = root.querySelector('option[value="2"]')
+    const data = root._vnode.component.data
+
+    one.selected = true
+    two.selected = false
+    triggerEvent('change', input)
+    await nextTick()
+    expect(data.value).toMatchObject([1])
+
+    one.selected = false
+    two.selected = true
+    triggerEvent('change', input)
+    await nextTick()
+    expect(data.value).toMatchObject([2])
+
+    one.selected = true
+    two.selected = true
+    triggerEvent('change', input)
+    await nextTick()
+    expect(data.value).toMatchObject([1, 2])
+
+    one.selected = false
+    two.selected = false
+    data.value = [1]
+    await nextTick()
+    expect(one.selected).toEqual(true)
+    expect(two.selected).toEqual(false)
+
+    one.selected = false
+    two.selected = false
+    data.value = [1, 2]
+    await nextTick()
+    expect(one.selected).toEqual(true)
+    expect(two.selected).toEqual(true)
+  })
+
   it('should work with composition session', async () => {
     const component = defineComponent({
       data() {
index ea1098dd19b9469abc4474caef64709aa4ce00c0..c7dfa40c2058f14c814503df715747bcdc9eb4e6 100644 (file)
@@ -166,11 +166,14 @@ export const vModelRadio: ModelDirective<HTMLInputElement> = {
 }
 
 export const vModelSelect: ModelDirective<HTMLSelectElement> = {
-  created(el, binding, vnode) {
+  created(el, { modifiers: { number } }, vnode) {
     addEventListener(el, 'change', () => {
       const selectedVal = Array.prototype.filter
         .call(el.options, (o: HTMLOptionElement) => o.selected)
-        .map(getValue)
+        .map(
+          (o: HTMLOptionElement) =>
+            number ? toNumber(getValue(o)) : getValue(o)
+        )
       el._assign(el.multiple ? selectedVal : selectedVal[0])
     })
     el._assign = getModelAssigner(vnode)