Skip to content

Commit 5293a74

Browse files
committed
tests for v-model text
1 parent 38a6e1f commit 5293a74

File tree

3 files changed

+171
-9
lines changed

3 files changed

+171
-9
lines changed

src/compile/compile.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,23 @@ function compileElement (el, options) {
8686
return makeTeriminalLinkFn(el, 'component', tag, options)
8787
}
8888
// check other directives
89+
var linkFn
8990
if (hasAttributes) {
9091
var directives = collectDirectives(el, options)
91-
return directives.length
92+
linkFn = directives.length
9293
? makeDirectivesLinkFn(directives)
9394
: null
9495
}
96+
// if the element is a textarea, we need to interpolate
97+
// its content on initial render.
98+
if (el.tagName === 'TEXTAREA') {
99+
var realLinkFn = linkFn
100+
linkFn = function (vm, el) {
101+
el.value = vm.$interpolate(el.value)
102+
if (realLinkFn) realLinkFn(vm, el)
103+
}
104+
}
105+
return linkFn
95106
}
96107

97108
/**

src/directives/model/text.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ module.exports = {
6161
_.nextTick(function () {
6262
var newVal = self._watcher.value
6363
self.update(newVal)
64-
if (cursorPos == null) {
65-
cursorPos = newVal.toString().length
64+
if (cursorPos != null) {
65+
el.setSelectionRange(cursorPos, cursorPos)
6666
}
67-
el.setSelectionRange(cursorPos, cursorPos)
6867
})
6968
}
7069
} else {

test/unit/specs/directives/model_spec.js

Lines changed: 157 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ if (_.inBrowser) {
1414
var el
1515
beforeEach(function () {
1616
el = document.createElement('div')
17+
el.style.display = 'none'
1718
document.body.appendChild(el)
1819
spyOn(_, 'warn')
1920
})
@@ -255,16 +256,167 @@ if (_.inBrowser) {
255256
expect(opts[2].selected).toBe(false)
256257
})
257258

258-
it('text', function () {
259-
259+
it('text', function (done) {
260+
var vm = new Vue({
261+
el: el,
262+
data: {
263+
test: 'b'
264+
},
265+
template: '<input v-model="test">'
266+
})
267+
expect(el.firstChild.value).toBe('b')
268+
vm.test = 'a'
269+
_.nextTick(function () {
270+
expect(el.firstChild.value).toBe('a')
271+
el.firstChild.value = 'c'
272+
trigger(el.firstChild, 'input')
273+
expect(vm.test).toBe('c')
274+
vm._directives[0].unbind()
275+
el.firstChild.value = 'd'
276+
trigger(el.firstChild, 'input')
277+
expect(vm.test).toBe('c')
278+
done()
279+
})
280+
})
281+
282+
it('text default value', function () {
283+
var vm = new Vue({
284+
el: el,
285+
data: {
286+
test: 'b'
287+
},
288+
template: '<input v-model="test" value="a">'
289+
})
290+
expect(vm.test).toBe('a')
291+
expect(el.firstChild.value).toBe('a')
292+
})
293+
294+
it('text lazy', function () {
295+
var vm = new Vue({
296+
el: el,
297+
data: {
298+
test: 'b'
299+
},
300+
template: '<input v-model="test" lazy>'
301+
})
302+
expect(el.firstChild.value).toBe('b')
303+
expect(vm.test).toBe('b')
304+
el.firstChild.value = 'c'
305+
trigger(el.firstChild, 'input')
306+
expect(vm.test).toBe('b')
307+
trigger(el.firstChild, 'change')
308+
expect(vm.test).toBe('c')
309+
})
310+
311+
it('text with filters', function (done) {
312+
var vm = new Vue({
313+
el: el,
314+
data: {
315+
test: 'b'
316+
},
317+
filters: {
318+
test: {
319+
write: function (val) {
320+
return val.toUpperCase()
321+
}
322+
}
323+
},
324+
template: '<input v-model="test | uppercase | test">'
325+
})
326+
expect(el.firstChild.value).toBe('B')
327+
el.firstChild.value = 'cc'
328+
trigger(el.firstChild, 'input')
329+
_.nextTick(function () {
330+
expect(el.firstChild.value).toBe('CC')
331+
expect(vm.test).toBe('CC')
332+
done()
333+
})
260334
})
261335

262-
it('text with filters', function () {
263-
336+
it('number', function () {
337+
var vm = new Vue({
338+
el: el,
339+
data: {
340+
test: 1
341+
},
342+
template: '<input v-model="test" number>'
343+
})
344+
el.firstChild.value = 2
345+
trigger(el.firstChild, 'input')
346+
expect(vm.test).toBe(2)
347+
})
348+
349+
it('IE9 cut and delete', function (done) {
350+
var ie9 = _.isIE9
351+
_.isIE9 = true
352+
var vm = new Vue({
353+
el: el,
354+
data: {
355+
test: 'aaa'
356+
},
357+
template: '<input v-model="test">'
358+
})
359+
var input = el.firstChild
360+
input.value = 'aa'
361+
trigger(input, 'cut')
362+
_.nextTick(function () {
363+
expect(vm.test).toBe('aa')
364+
input.value = 'a'
365+
trigger(input, 'keyup', function (e) {
366+
e.keyCode = 8
367+
})
368+
expect(vm.test).toBe('a')
369+
// teardown
370+
vm._directives[0].unbind()
371+
input.value = 'bbb'
372+
trigger(input, 'keyup', function (e) {
373+
e.keyCode = 8
374+
})
375+
expect(vm.test).toBe('a')
376+
_.isIE9 = ie9
377+
done()
378+
})
264379
})
265380

266381
it('text + compositionevents', function () {
267-
382+
var vm = new Vue({
383+
el: el,
384+
data: {
385+
test: 'aaa',
386+
test2: 'bbb'
387+
},
388+
template: '<input v-model="test"><input v-model="test2 | uppsercase">'
389+
})
390+
var input = el.firstChild
391+
var input2 = el.childNodes[1]
392+
trigger(input, 'compositionstart')
393+
trigger(input2, 'compositionstart')
394+
input.value = input2.value = 'ccc'
395+
// input before composition unlock should not call set
396+
trigger(input, 'input')
397+
trigger(input2, 'input')
398+
expect(vm.test).toBe('aaa')
399+
expect(vm.test2).toBe('bbb')
400+
// after composition unlock it should work
401+
trigger(input, 'compositionend')
402+
trigger(input2, 'compositionend')
403+
trigger(input, 'input')
404+
trigger(input2, 'input')
405+
expect(vm.test).toBe('ccc')
406+
expect(vm.test2).toBe('ccc')
407+
})
408+
409+
it('textarea', function () {
410+
var vm = new Vue({
411+
el: el,
412+
data: {
413+
test: 'b',
414+
b: 'BB'
415+
},
416+
template: '<textarea v-model="test">a {{b}} c</textarea>'
417+
})
418+
expect(vm.test).toBe('a BB c')
419+
expect(el.firstChild.value).toBe('a BB c')
268420
})
269421

270422
it('warn invalid tag', function () {

0 commit comments

Comments
 (0)