From 41838c8e8632ba78791996fbc697080b2764bb6a Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 21 Dec 2017 11:06:43 -0500 Subject: [PATCH] feat: support v-model dynamic type binding for v-bind="object" close #7296 --- src/platforms/web/compiler/modules/model.js | 15 +++++- .../features/directives/model-dynamic.spec.js | 50 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/platforms/web/compiler/modules/model.js b/src/platforms/web/compiler/modules/model.js index 2ef37e836d3..a7426c0204f 100644 --- a/src/platforms/web/compiler/modules/model.js +++ b/src/platforms/web/compiler/modules/model.js @@ -26,8 +26,19 @@ import { function preTransformNode (el: ASTElement, options: CompilerOptions) { if (el.tag === 'input') { const map = el.attrsMap - if (map['v-model'] && (map['v-bind:type'] || map[':type'])) { - const typeBinding: any = getBindingAttr(el, 'type') + if (!map['v-model']) { + return + } + + let typeBinding + if (map[':type'] || map['v-bind:type']) { + typeBinding = getBindingAttr(el, 'type') + } + if (!typeBinding && map['v-bind']) { + typeBinding = `(${map['v-bind']}).type` + } + + if (typeBinding) { const ifCondition = getAndRemoveAttr(el, 'v-if', true) const ifConditionExtra = ifCondition ? `&&(${ifCondition})` : `` const hasElse = getAndRemoveAttr(el, 'v-else', true) != null diff --git a/test/unit/features/directives/model-dynamic.spec.js b/test/unit/features/directives/model-dynamic.spec.js index a5c18fe82b2..88a910fedfa 100644 --- a/test/unit/features/directives/model-dynamic.spec.js +++ b/test/unit/features/directives/model-dynamic.spec.js @@ -127,6 +127,56 @@ describe('Directive v-model dynamic input type', () => { expect(vm.data.text).toBe('foo') }).then(done) }) + + it('with v-bind', done => { + const vm = new Vue({ + data: { + data: { + text: 'foo', + checkbox: true + }, + inputs: [{ id: 'one', type: 'text' }, { id: 'two', type: 'checkbox' }] + }, + template: `
+ +
` + }).$mount() + document.body.appendChild(vm.$el) + + let el1 = vm.$el.children[0] + expect(el1.id).toBe('one') + expect(el1.type).toBe('text') + expect(el1.value).toBe('foo') + el1.value = 'bar' + triggerEvent(el1, 'input') + expect(vm.data.text).toBe('bar') + + let el2 = vm.$el.children[1] + expect(el2.id).toBe('two') + expect(el2.type).toBe('checkbox') + expect(el2.checked).toBe(true) + el2.click() + expect(vm.data.checkbox).toBe(false) + + // now in reverse! + vm.inputs.reverse() + waitForUpdate(() => { + el1 = vm.$el.children[0] + expect(el1.id).toBe('two') + expect(el1.type).toBe('checkbox') + expect(el1.checked).toBe(false) + el1.click() + expect(vm.data.checkbox).toBe(true) + + el2 = vm.$el.children[1] + expect(el2.id).toBe('one') + expect(el2.type).toBe('text') + expect(el2.value).toBe('bar') + el2.value = 'foo' + triggerEvent(el2, 'input') + expect(vm.data.text).toBe('foo') + }).then(done) + }) }) function assertInputWorks (vm, type, chain) {