Skip to content

Commit ff64dd6

Browse files
committed
new syntax for v-model object value bindings
1 parent 96ac229 commit ff64dd6

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

src/deprecations.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ if (process.env.NODE_ENV !== 'production') {
186186
'handler explicitly returns true. See https://github.com/yyx990803/vue/issues/1175 ' +
187187
'for more details.'
188188
)
189+
},
190+
191+
MODEL_EXP: function (exp) {
192+
warn(
193+
'Params "exp", "true-exp" and "false-exp" for v-model will be deprecated in 1.0.0. ' +
194+
'Use "bind-value", "bind-true-value" and "bind-false-value" instead.'
195+
)
189196
}
190197

191198
}

src/directives/attr.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
// xlink
22
var xlinkNS = 'http://www.w3.org/1999/xlink'
33
var xlinkRE = /^xlink:/
4+
5+
// these input element attributes should also set their
6+
// corresponding properties
47
var inputProps = {
58
value: 1,
69
checked: 1,
710
selected: 1
811
}
912

13+
// these attributes should set a hidden property for
14+
// binding v-model to object values
15+
var modelProps = {
16+
value: '_value',
17+
'true-value': '_trueValue',
18+
'false-value': '_falseValue'
19+
}
20+
1021
module.exports = {
1122

1223
priority: 850,
@@ -56,5 +67,10 @@ module.exports = {
5667
} else {
5768
this.el.removeAttribute(attr)
5869
}
70+
// set model props
71+
var modelProp = modelProps[attr]
72+
if (modelProp) {
73+
this.el[modelProp] = value
74+
}
5975
}
6076
}

src/directives/model/checkbox.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ module.exports = {
99
var falseExp = this.param('false-exp')
1010
var scope = this._scope || this.vm
1111

12+
if (process.env.NODE_ENV !== 'production' && (trueExp || falseExp)) {
13+
_.deprecation.MODEL_EXP(this.expression)
14+
}
15+
1216
this._matchValue = function (value) {
13-
if (trueExp !== null) {
17+
if (el.hasOwnProperty('_trueValue')) {
18+
return _.looseEqual(value, el._trueValue)
19+
} else if (trueExp !== null) {
1420
return _.looseEqual(value, scope.$eval(trueExp))
1521
} else {
1622
return !!value
@@ -19,6 +25,12 @@ module.exports = {
1925

2026
function getValue () {
2127
var val = el.checked
28+
if (val && el.hasOwnProperty('_trueValue')) {
29+
return el._trueValue
30+
}
31+
if (!val && el.hasOwnProperty('_falseValue')) {
32+
return el._falseValue
33+
}
2234
if (val && trueExp !== null) {
2335
val = scope.$eval(trueExp)
2436
}

src/directives/model/radio.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ module.exports = {
99
var expression = this.param('exp')
1010
var scope = this._scope || this.vm
1111

12+
if (process.env.NODE_ENV !== 'production' && expression) {
13+
_.deprecation.MODEL_EXP(this.expression)
14+
}
15+
1216
this.getValue = function () {
17+
// value overwrite via bind-value
18+
if (el.hasOwnProperty('_value')) {
19+
return el._value
20+
}
1321
var val = el.value
1422
if (number) {
1523
val = _.toNumber(val)

test/unit/specs/directives/model_spec.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,34 @@ if (_.inBrowser) {
108108
})
109109
})
110110

111+
it('radio expression (new syntax)', function (done) {
112+
var vm = new Vue({
113+
el: el,
114+
data: {
115+
test: false,
116+
test2: 'string1',
117+
expression1: 'string1',
118+
expression2: 'string2'
119+
},
120+
template:
121+
'<input type="radio" value="1" v-model="test" name="test" bind-value="true">' +
122+
'<input type="radio" value="0" v-model="test" name="test" bind-value="false">' +
123+
'<input type="radio" value="1" v-model="test2" name="test2" bind-value="expression1">' +
124+
'<input type="radio" value="0" v-model="test2" name="test2" bind-value="expression2">'
125+
})
126+
expect(el.childNodes[0].checked).toBe(false)
127+
expect(el.childNodes[1].checked).toBe(true)
128+
expect(el.childNodes[2].checked).toBe(true)
129+
expect(el.childNodes[3].checked).toBe(false)
130+
_.nextTick(function () {
131+
el.childNodes[0].click()
132+
expect(vm.test).toBe(true)
133+
el.childNodes[3].click()
134+
expect(vm.test2).toBe('string2')
135+
done()
136+
})
137+
})
138+
111139
it('checkbox', function (done) {
112140
var vm = new Vue({
113141
el: el,
@@ -167,6 +195,32 @@ if (_.inBrowser) {
167195
})
168196
})
169197

198+
it('checkbox expression (new syntax)', function (done) {
199+
var vm = new Vue({
200+
el: el,
201+
data: {
202+
test: '',
203+
expression1: 'aTrueValue',
204+
expression2: 'aFalseValue'
205+
},
206+
template: '<input type="checkbox" v-model="test" bind-true-value="expression1" bind-false-value="expression2">'
207+
})
208+
expect(vm.test).toBe('')
209+
el.firstChild.click()
210+
expect(vm.test).toBe('aTrueValue')
211+
expect(el.firstChild.checked).toBe(true)
212+
el.firstChild.click()
213+
expect(vm.test).toBe('aFalseValue')
214+
expect(el.firstChild.checked).toBe(false)
215+
_.nextTick(function () {
216+
vm.test = 'aTrueValue'
217+
_.nextTick(function () {
218+
expect(el.firstChild.checked).toBe(true)
219+
done()
220+
})
221+
})
222+
})
223+
170224
it('select', function (done) {
171225
var vm = new Vue({
172226
el: el,

0 commit comments

Comments
 (0)