Skip to content

Commit

Permalink
fix(v-model): use stricter check for <select> option update
Browse files Browse the repository at this point in the history
close #6112
  • Loading branch information
yyx990803 committed Jul 19, 2017
1 parent be3dc9c commit c70addf
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 13 deletions.
17 changes: 4 additions & 13 deletions src/platforms/web/runtime/directives/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default {
if (isIE || isEdge) {
setTimeout(cb, 0)
}
el._vOptions = [].map.call(el.options, getValue)
} else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
el._vModifiers = binding.modifiers
if (!binding.modifiers.lazy) {
Expand All @@ -56,10 +57,9 @@ export default {
// it's possible that the value is out-of-sync with the rendered options.
// detect such cases and filter out values that no longer has a matching
// option in the DOM.
const needReset = el.multiple
? binding.value.some(v => hasNoMatchingOption(v, el.options))
: binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, el.options)
if (needReset) {
const prevOptions = el._vOptions
const curOptions = el._vOptions = [].map.call(el.options, getValue)
if (curOptions.some((o, i) => !looseEqual(o, prevOptions[i]))) {
trigger(el, 'change')
}
}
Expand Down Expand Up @@ -101,15 +101,6 @@ function setSelected (el, binding, vm) {
}
}

function hasNoMatchingOption (value, options) {
for (let i = 0, l = options.length; i < l; i++) {
if (looseEqual(getValue(options[i]), value)) {
return false
}
}
return true
}

function getValue (option) {
return '_value' in option
? option._value
Expand Down
18 changes: 18 additions & 0 deletions test/unit/features/directives/model-select.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,4 +471,22 @@ describe('Directive v-model select', () => {
expect(vm.$el.childNodes[0].selected).toBe(true)
}).then(done)
})

// #6112
it('should not set non-matching value to undefined if options did not change', done => {
const vm = new Vue({
data: {
test: '1'
},
template:
'<select v-model="test">' +
'<option>a</option>' +
'</select>'
}).$mount()

vm.test = '2'
waitForUpdate(() => {
expect(vm.test).toBe('2')
}).then(done)
})
})

0 comments on commit c70addf

Please sign in to comment.