From 2feeed68ef8e0b9d7b0605a59630e0c0df56206d Mon Sep 17 00:00:00 2001
From: Wesley Cho <wesley.cho@gmail.com>
Date: Tue, 14 Jun 2016 08:22:06 -0700
Subject: [PATCH] fix(input): update $viewValue when cleared

- Fix when user clicks clear button in an input element in IE, $viewValue not being correctly updated
---
 src/ng/directive/input.js | 20 ++++++++++++++++++--
 src/ng/sniffer.js         |  2 +-
 test/ng/snifferSpec.js    |  2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index 969d53c634d2..cc237a6a3e19 100644
--- a/src/ng/directive/input.js
+++ b/src/ng/directive/input.js
@@ -1126,7 +1126,11 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
     });
   }
 
-  var timeout;
+  var timeout, oldVal;
+  var viewValueUpdated = false, msieInput = msie >= 10 && msie <= 11;
+  if (msieInput) {
+    oldVal = element.val();
+  }
 
   var listener = function(ev) {
     if (timeout) {
@@ -1152,10 +1156,18 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
     }
   };
 
+  function ieListener(ev) {
+    var val = element.val();
+    if (val === oldVal && !viewValueUpdated) return;
+    oldVal = val;
+    viewValueUpdated = false;
+    listener(ev);
+  }
+
   // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
   // input event on backspace, delete or cut
   if ($sniffer.hasEvent('input')) {
-    element.on('input', listener);
+    element.on('input', msie ? ieListener : listener);
   } else {
     var deferListener = function(ev, input, origValue) {
       if (!timeout) {
@@ -1212,6 +1224,10 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
     // Workaround for Firefox validation #12102.
     var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;
     if (element.val() !== value) {
+      // Workaround for IE 10 & 11 input updates #11193
+      if (msieInput) {
+        viewValueUpdated = true;
+      }
       element.val(value);
     }
   };
diff --git a/src/ng/sniffer.js b/src/ng/sniffer.js
index 5bc32fdf1db6..b03dc119c2ab 100644
--- a/src/ng/sniffer.js
+++ b/src/ng/sniffer.js
@@ -73,7 +73,7 @@ function $SnifferProvider() {
         // when cut operation is performed.
         // IE10+ implements 'input' event but it erroneously fires under various situations,
         // e.g. when placeholder changes, or a form is focused.
-        if (event === 'input' && msie <= 11) return false;
+        if (event === 'input' && msie <= 9) return false;
 
         if (isUndefined(eventSupport[event])) {
           var divElm = document.createElement('div');
diff --git a/test/ng/snifferSpec.js b/test/ng/snifferSpec.js
index dd52de11ff29..8db37378c0cb 100644
--- a/test/ng/snifferSpec.js
+++ b/test/ng/snifferSpec.js
@@ -135,7 +135,7 @@ describe('$sniffer', function() {
       // IE10+ implementation is fubared when mixed with placeholders
       mockDivElement = {oninput: noop};
 
-      expect($sniffer.hasEvent('input')).toBe(!(msie && msie <= 11));
+      expect($sniffer.hasEvent('input')).toBe(!(msie && msie <= 9));
     });
   });