From d21dff21ed8beb015ad911f11d57cceb56fc439f Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 28 Oct 2014 01:25:45 -0700 Subject: [PATCH] fix(ngmodel): fixing many keys incorrectly marking inputs as dirty --- src/ng/directive/input.js | 12 +++++++++--- test/ng/directive/inputSpec.js | 23 +++++++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 3ac9de93..59650db3 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -973,6 +973,10 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { } var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; + } if (composing) return; var value = element.val(), event = ev && ev.type; @@ -999,11 +1003,13 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { } else { var timeout; - var deferListener = function(ev) { + var deferListener = function(ev, input, origValue) { if (!timeout) { timeout = $browser.defer(function() { - listener(ev); timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } }); } }; @@ -1015,7 +1021,7 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { // command modifiers arrows if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; - deferListener(event); + deferListener(event, this, this.value); }); // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index ee48e1b6..9fe5d97f 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1804,7 +1804,7 @@ describe('input', function() { } }); - describe('"paste" and "cut" events', function() { + describe('"keydown", "paste" and "cut" events', function() { beforeEach(function() { // Force browser to report a lack of an 'input' event $sniffer.hasEvent = function(eventName) { @@ -1812,9 +1812,13 @@ describe('input', function() { }; }); - it('should update the model on "paste" event', function() { + it('should update the model on "paste" event if the input value changes', function() { compileInput(''); + browserTrigger(inputElm, 'keydown'); + $browser.defer.flush(); + expect(inputElm).toBePristine(); + inputElm.val('mark'); browserTrigger(inputElm, 'paste'); $browser.defer.flush(); @@ -1830,6 +1834,21 @@ describe('input', function() { expect(scope.name).toEqual('john'); }); + it('should cancel the delayed dirty if a change occurs', function() { + compileInput(''); + var ctrl = inputElm.controller('ngModel'); + + browserTrigger(inputElm, 'keydown', {target: inputElm[0]}); + inputElm.val('f'); + browserTrigger(inputElm, 'change'); + expect(inputElm).toBeDirty(); + + ctrl.$setPristine(); + scope.$apply(); + + $browser.defer.flush(); + expect(inputElm).toBePristine(); + }); });