Skip to content

Commit 5b668a9

Browse files
committed
warn non-Array value for <select multiple> (close #3191)
1 parent 41a3b79 commit 5b668a9

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

src/platforms/web/runtime/directives/model.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default {
3232
}
3333
}
3434
if (vnode.tag === 'select') {
35-
setSelected(el, binding.value)
35+
setSelected(el, binding, vnode.context)
3636
} else {
3737
if (!isAndroid) {
3838
el.addEventListener('compositionstart', onCompositionStart)
@@ -45,27 +45,36 @@ export default {
4545
}
4646
},
4747
componentUpdated (el, binding, vnode) {
48-
const val = binding.value
4948
if (vnode.tag === 'select') {
50-
setSelected(el, val)
49+
setSelected(el, binding, vnode.context)
5150
// in case the options rendered by v-for have changed,
5251
// it's possible that the value is out-of-sync with the rendered options.
5352
// detect such cases and filter out values that no longer has a matchig
5453
// option in the DOM.
5554
const needReset = el.multiple
56-
? val.some(v => hasNoMatchingOption(v, el.options))
57-
: hasNoMatchingOption(val, el.options)
55+
? binding.value.some(v => hasNoMatchingOption(v, el.options))
56+
: hasNoMatchingOption(binding.value, el.options)
5857
if (needReset) {
5958
trigger(el, 'change')
6059
}
6160
}
6261
}
6362
}
6463

65-
function setSelected (el, value) {
64+
function setSelected (el, binding, vm) {
65+
const value = binding.value
6666
const isMultiple = el.multiple
6767
if (!isMultiple) {
6868
el.selectedIndex = -1
69+
} else if (!Array.isArray(value)) {
70+
process.env.NODE_ENV !== 'production' && warn(
71+
`<select multiple v-model="${binding.expression}"> ` +
72+
`expects an Array value for its binding, but got ${
73+
Object.prototype.toString.call(value).slice(8, -1)
74+
}`,
75+
vm
76+
)
77+
return
6978
}
7079
for (let i = 0, l = el.options.length; i < l; i++) {
7180
const option = el.options[i]

test/unit/features/directives/model-select.spec.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,16 @@ describe('Directive v-model select', () => {
203203
expect('inline selected attributes on <option> will be ignored when using v-model')
204204
.toHaveBeenWarned()
205205
})
206+
207+
it('should warn multiple with non-Array value', () => {
208+
const vm = new Vue({
209+
data: {
210+
test: 'meh'
211+
},
212+
template:
213+
'<select v-model="test" multiple></select>'
214+
}).$mount()
215+
expect('<select multiple v-model="test"> expects an Array value for its binding, but got String')
216+
.toHaveBeenWarned()
217+
})
206218
})

0 commit comments

Comments
 (0)