fix(runtime-dom): v-model should support number modifier with select tag (#2308)
close #2252
This commit is contained in:
parent
3d3323f452
commit
d744b8a2dc
@ -681,6 +681,108 @@ describe('vModel', () => {
|
|||||||
expect(bar.selected).toEqual(true)
|
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 () => {
|
it('should work with composition session', async () => {
|
||||||
const component = defineComponent({
|
const component = defineComponent({
|
||||||
data() {
|
data() {
|
||||||
|
@ -166,11 +166,14 @@ export const vModelRadio: ModelDirective<HTMLInputElement> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
export const vModelSelect: ModelDirective<HTMLSelectElement> = {
|
||||||
created(el, binding, vnode) {
|
created(el, { modifiers: { number } }, vnode) {
|
||||||
addEventListener(el, 'change', () => {
|
addEventListener(el, 'change', () => {
|
||||||
const selectedVal = Array.prototype.filter
|
const selectedVal = Array.prototype.filter
|
||||||
.call(el.options, (o: HTMLOptionElement) => o.selected)
|
.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(el.multiple ? selectedVal : selectedVal[0])
|
||||||
})
|
})
|
||||||
el._assign = getModelAssigner(vnode)
|
el._assign = getModelAssigner(vnode)
|
||||||
|
Loading…
Reference in New Issue
Block a user