From 06d0955074f79de553cc34fbf945045dc458e064 Mon Sep 17 00:00:00 2001 From: Vojta Jina Date: Fri, 30 Mar 2012 12:07:19 -0700 Subject: feat(ngModel): update model on each key stroke (revert ngModelInstant) It turns out that listening only on "blur" event is not sufficient in many scenarios, especially when you use form validation you always had to use ngModelnstant e.g. if you want to disable a button based on valid/invalid form. The feedback we got from our apps as well as external apps is that the ngModelInstant should be the default. In the future we might provide alternative ways of suppressing updates on each key stroke, but it's not going to be the default behavior. Apps already using the ngModelInstant can safely remove it from their templates. Input fields without ngModelInstant directive will start propagating the input changes into the model on each key stroke. --- test/BinderSpec.js | 14 ----------- test/ng/directive/formSpec.js | 15 ++++++----- test/ng/directive/inputSpec.js | 57 +++++++++++------------------------------- 3 files changed, 24 insertions(+), 62 deletions(-) (limited to 'test') diff --git a/test/BinderSpec.js b/test/BinderSpec.js index 306cbc43..6d5dd91e 100644 --- a/test/BinderSpec.js +++ b/test/BinderSpec.js @@ -142,20 +142,6 @@ describe('Binder', function() { expect(html.indexOf('action="foo();"')).toBeGreaterThan(0); }); - it('RepeaterAdd', inject(function($rootScope, $compile) { - element = $compile('
')($rootScope); - $rootScope.items = [{x:'a'}, {x:'b'}]; - $rootScope.$apply(); - var first = childNode(element, 1); - var second = childNode(element, 2); - expect(first.val()).toEqual('a'); - expect(second.val()).toEqual('b'); - - first.val('ABC'); - browserTrigger(first, 'blur'); - expect($rootScope.items[0].x).toEqual('ABC'); - })); - it('ItShouldRemoveExtraChildrenWhenIteratingOverHash', inject(function($rootScope, $compile) { element = $compile('
{{i}}
')($rootScope); var items = {}; diff --git a/test/ng/directive/formSpec.js b/test/ng/directive/formSpec.js index 5c34b5ad..491a31db 100644 --- a/test/ng/directive/formSpec.js +++ b/test/ng/directive/formSpec.js @@ -1,7 +1,7 @@ 'use strict'; describe('form', function() { - var doc, control, scope, $compile; + var doc, control, scope, $compile, changeInputValue; beforeEach(module(function($compileProvider) { $compileProvider.directive('storeModelCtrl', function() { @@ -14,9 +14,14 @@ describe('form', function() { }); })); - beforeEach(inject(function($injector) { + beforeEach(inject(function($injector, $sniffer) { $compile = $injector.get('$compile'); scope = $injector.get('$rootScope'); + + changeInputValue = function(elm, value) { + elm.val(value); + browserTrigger(elm, $sniffer.hasEvent('input') ? 'input' : 'change'); + }; })); afterEach(function() { @@ -126,10 +131,8 @@ describe('form', function() { var inputA = doc.find('input').eq(0), inputB = doc.find('input').eq(1); - inputA.val('val1'); - browserTrigger(inputA, 'blur'); - inputB.val('val2'); - browserTrigger(inputB, 'blur'); + changeInputValue(inputA, 'val1'); + changeInputValue(inputB, 'val2'); expect(scope.firstName).toBe('val1'); expect(scope.lastName).toBe('val2'); diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 734cb34d..395f37c3 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -236,7 +236,7 @@ describe('NgModelController', function() { describe('ng-model', function() { it('should set css classes (ng-valid, ng-invalid, ng-pristine, ng-dirty)', - inject(function($compile, $rootScope) { + inject(function($compile, $rootScope, $sniffer) { var element = $compile('')($rootScope); $rootScope.$digest(); @@ -254,14 +254,14 @@ describe('ng-model', function() { expect(element.hasClass('ng-invalid-email')).toBe(true); element.val('invalid-again'); - browserTrigger(element, 'blur'); + browserTrigger(element, $sniffer.hasEvent('input') ? 'input' : 'change'); expect(element).toBeInvalid(); expect(element).toBeDirty(); expect(element.hasClass('ng-valid-email')).toBe(false); expect(element.hasClass('ng-invalid-email')).toBe(true); element.val('vojta@google.com'); - browserTrigger(element, 'blur'); + browserTrigger(element, $sniffer.hasEvent('input') ? 'input' : 'change'); expect(element).toBeValid(); expect(element).toBeDirty(); expect(element.hasClass('ng-valid-email')).toBe(true); @@ -282,7 +282,7 @@ describe('ng-model', function() { describe('input', function() { - var formElm, inputElm, scope, $compile; + var formElm, inputElm, scope, $compile, changeInputValueTo; function compileInput(inputHtml) { formElm = jqLite('
' + inputHtml + '
'); @@ -290,14 +290,14 @@ describe('input', function() { $compile(formElm)(scope); } - function changeInputValueTo(value) { - inputElm.val(value); - browserTrigger(inputElm, 'blur'); - } - - beforeEach(inject(function($injector) { + beforeEach(inject(function($injector, $sniffer) { $compile = $injector.get('$compile'); scope = $injector.get('$rootScope'); + + changeInputValueTo = function(value) { + inputElm.val(value); + browserTrigger(inputElm, $sniffer.hasEvent('input') ? 'input' : 'change'); + }; })); afterEach(function() { @@ -379,7 +379,7 @@ describe('input', function() { it('should ignore input without ng-model attr', function() { compileInput(''); - browserTrigger(inputElm, 'blur'); + changeInputValueTo(''); expect(inputElm.hasClass('ng-valid')).toBe(false); expect(inputElm.hasClass('ng-invalid')).toBe(false); expect(inputElm.hasClass('ng-pristine')).toBe(false); @@ -715,7 +715,7 @@ describe('input', function() { expect(inputElm[1].checked).toBe(true); expect(inputElm[2].checked).toBe(false); - browserTrigger(inputElm[2]); + browserTrigger(inputElm[2], 'click'); expect(scope.color).toBe('blue'); }); @@ -735,7 +735,7 @@ describe('input', function() { expect(inputElm[0].checked).toBe(true); expect(inputElm[1].checked).toBe(false); - browserTrigger(inputElm[1]); + browserTrigger(inputElm[1], 'click'); expect(scope.value).toBe('red'); scope.$apply(function() { @@ -753,7 +753,7 @@ describe('input', function() { it('should ignore checkbox without ng-model attr', function() { compileInput(''); - browserTrigger(inputElm, 'blur'); + changeInputValueTo(''); expect(inputElm.hasClass('ng-valid')).toBe(false); expect(inputElm.hasClass('ng-invalid')).toBe(false); expect(inputElm.hasClass('ng-pristine')).toBe(false); @@ -851,7 +851,7 @@ describe('input', function() { compileInput(''); inputElm = formElm.find('textarea'); - browserTrigger(inputElm, 'blur'); + changeInputValueTo(''); expect(inputElm.hasClass('ng-valid')).toBe(false); expect(inputElm.hasClass('ng-invalid')).toBe(false); expect(inputElm.hasClass('ng-pristine')).toBe(false); @@ -1053,33 +1053,6 @@ describe('input', function() { }); - describe('ng-model-instant', function() { - - it('should bind keydown, change, input events', inject(function($browser) { - compileInput(''); - - inputElm.val('value1'); - browserTrigger(inputElm, 'keydown'); - - // should be async (because of keydown) - expect(scope.value).toBeUndefined(); - - $browser.defer.flush(); - expect(scope.value).toBe('value1'); - - inputElm.val('value2'); - browserTrigger(inputElm, 'change'); - expect(scope.value).toBe('value2'); - - if (msie < 9) return; - - inputElm.val('value3'); - browserTrigger(inputElm, 'input'); - expect(scope.value).toBe('value3'); - })); - }); - - describe('ng-value', function() { it('should evaluate and set constant expressions', function() { -- cgit v1.2.3