Skip to content

Commit

Permalink
fix(runtime-dom): v-model should support number modifier with select …
Browse files Browse the repository at this point in the history
…tag (#2308)

close #2252
  • Loading branch information
edison1105 authored Oct 7, 2020
1 parent 3d3323f commit d744b8a
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 2 deletions.
102 changes: 102 additions & 0 deletions packages/runtime-dom/__tests__/directives/vModel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
7 changes: 5 additions & 2 deletions packages/runtime-dom/src/directives/vModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit d744b8a

Please sign in to comment.