Skip to content

Commit 69c7339

Browse files
yyx990803hefeng
authored and
hefeng
committed
feat: support v-model dynamic type binding for v-bind="object"
close vuejs#7296
1 parent 130137e commit 69c7339

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

src/platforms/web/compiler/modules/model.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,19 @@ import {
2626
function preTransformNode (el: ASTElement, options: CompilerOptions) {
2727
if (el.tag === 'input') {
2828
const map = el.attrsMap
29-
if (map['v-model'] && (map['v-bind:type'] || map[':type'])) {
30-
const typeBinding: any = getBindingAttr(el, 'type')
29+
if (!map['v-model']) {
30+
return
31+
}
32+
33+
let typeBinding
34+
if (map[':type'] || map['v-bind:type']) {
35+
typeBinding = getBindingAttr(el, 'type')
36+
}
37+
if (!typeBinding && map['v-bind']) {
38+
typeBinding = `(${map['v-bind']}).type`
39+
}
40+
41+
if (typeBinding) {
3142
const ifCondition = getAndRemoveAttr(el, 'v-if', true)
3243
const ifConditionExtra = ifCondition ? `&&(${ifCondition})` : ``
3344
const hasElse = getAndRemoveAttr(el, 'v-else', true) != null

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

+50
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,56 @@ describe('Directive v-model dynamic input type', () => {
127127
expect(vm.data.text).toBe('foo')
128128
}).then(done)
129129
})
130+
131+
it('with v-bind', done => {
132+
const vm = new Vue({
133+
data: {
134+
data: {
135+
text: 'foo',
136+
checkbox: true
137+
},
138+
inputs: [{ id: 'one', type: 'text' }, { id: 'two', type: 'checkbox' }]
139+
},
140+
template: `<div>
141+
<input v-for="i in inputs" v-bind="i" v-model="data[i.type]">
142+
</div>`
143+
}).$mount()
144+
document.body.appendChild(vm.$el)
145+
146+
let el1 = vm.$el.children[0]
147+
expect(el1.id).toBe('one')
148+
expect(el1.type).toBe('text')
149+
expect(el1.value).toBe('foo')
150+
el1.value = 'bar'
151+
triggerEvent(el1, 'input')
152+
expect(vm.data.text).toBe('bar')
153+
154+
let el2 = vm.$el.children[1]
155+
expect(el2.id).toBe('two')
156+
expect(el2.type).toBe('checkbox')
157+
expect(el2.checked).toBe(true)
158+
el2.click()
159+
expect(vm.data.checkbox).toBe(false)
160+
161+
// now in reverse!
162+
vm.inputs.reverse()
163+
waitForUpdate(() => {
164+
el1 = vm.$el.children[0]
165+
expect(el1.id).toBe('two')
166+
expect(el1.type).toBe('checkbox')
167+
expect(el1.checked).toBe(false)
168+
el1.click()
169+
expect(vm.data.checkbox).toBe(true)
170+
171+
el2 = vm.$el.children[1]
172+
expect(el2.id).toBe('one')
173+
expect(el2.type).toBe('text')
174+
expect(el2.value).toBe('bar')
175+
el2.value = 'foo'
176+
triggerEvent(el2, 'input')
177+
expect(vm.data.text).toBe('foo')
178+
}).then(done)
179+
})
130180
})
131181

132182
function assertInputWorks (vm, type, chain) {

0 commit comments

Comments
 (0)