Skip to content

Commit 5c4c317

Browse files
committed
persist select with no selected option on append (fix vuejs#1008)
1 parent 92319e6 commit 5c4c317

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

src/directives/model/select.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ module.exports = {
77
bind: function () {
88
var self = this
99
var el = this.el
10+
// update DOM using latest value.
11+
this.forceUpdate = function () {
12+
if (self._watcher) {
13+
self.update(self._watcher.get())
14+
}
15+
}
1016
// check options param
1117
var optionsParam = this._checkParam('options')
1218
if (optionsParam) {
@@ -27,6 +33,11 @@ module.exports = {
2733
}
2834
_.on(el, 'change', this.listener)
2935
checkInitialValue.call(this)
36+
// All major browsers except Firefox resets
37+
// selectedIndex with value -1 to 0 when the element
38+
// is appended to a new parent, therefore we have to
39+
// force a DOM update whenever that happens...
40+
this.vm.$on('hook:attached', this.forceUpdate)
3041
},
3142

3243
update: function (value) {
@@ -48,6 +59,7 @@ module.exports = {
4859

4960
unbind: function () {
5061
_.off(this.el, 'change', this.listener)
62+
this.vm.$off('hook:attached', this.forceUpdate)
5163
if (this.optionWatcher) {
5264
this.optionWatcher.teardown()
5365
}
@@ -68,9 +80,7 @@ function initOptions (expression) {
6880
if (_.isArray(value)) {
6981
self.el.innerHTML = ''
7082
buildOptions(self.el, value)
71-
if (self._watcher) {
72-
self.update(self._watcher.value)
73-
}
83+
self.forceUpdate()
7484
} else {
7585
_.warn('Invalid options value for v-model: ' + value)
7686
}

test/unit/specs/directives/model_spec.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,29 @@ if (_.inBrowser) {
140140
})
141141
})
142142

143-
it('select default value', function () {
143+
it('select persist non-selected on append', function () {
144+
var vm = new Vue({
145+
el: el,
146+
data: {
147+
test: null
148+
},
149+
replace: true,
150+
template:
151+
'<select v-model="test">' +
152+
'<option>a</option>' +
153+
'<option>b</option>' +
154+
'<option>c</option>' +
155+
'</select>'
156+
})
157+
expect(vm.$el.value).toBe('')
158+
expect(vm.$el.selectedIndex).toBe(-1)
159+
vm.$remove()
160+
vm.$appendTo(document.body)
161+
expect(vm.$el.value).toBe('')
162+
expect(vm.$el.selectedIndex).toBe(-1)
163+
})
164+
165+
it('select template default value', function () {
144166
var vm = new Vue({
145167
el: el,
146168
data: {

0 commit comments

Comments
 (0)