19

IE has an "X" in each text input that will clear the input. However, when clicking this button, while it clears the textbox, it does not update the Angular model that the input is bound to.

<input type="text" ng-model="name" />

See http://jsfiddle.net/p5x1zwr9/ for an example of the behavior.

See http://youtu.be/LFaEwliTzpQ for a video of the behavior.

I am using IE 11.

EDIT: There does seem to be a solution for Knockout, but I don't know how to apply it to AngularJS: Handle IE 9 & 10's clear button with Knockout binding

UPDATE: Jonathan Sampson helped me realize that this actually worked in AngularJS versions prior to 1.3.6 so this may be a new Angular bug.

UPDATE: Opened issue: https://github.com/angular/angular.js/issues/11193

Community
  • 1
  • 1
dprothero
  • 2,683
  • 2
  • 21
  • 28
  • 1
    Does this repro *outside* of jsfiddle? If you load Angular 1.2.1 within jsfiddle, there is no problem: http://jsfiddle.net/p5x1zwr9/1/. – Sampson Feb 20 '15 at 21:49
  • It does repro outside of jsfiddle, that's how we originally discovered it. The app we're building is using Angular 1.3.8, so that's why I'm loading that version. – dprothero Feb 20 '15 at 21:54
  • 1
    It looks like this behavior broke in 1.3.6. – Sampson Feb 20 '15 at 22:00
  • Agreed, just tested it. May need to file a bug with the Angular team. – dprothero Feb 20 '15 at 22:09

6 Answers6

18

The X button in input forms is native for IE10+ and you can`t do anything about it, but only hide it with CSS:

input[type=text]::-ms-clear {
   display: none;
}

Then you can create your own directive to mimic this kind of behaviour. Just create a span, position it inside of an input and add ng-click to it, which will clear the model value of the input.

Michał Lach
  • 1,291
  • 4
  • 18
  • 37
  • There does seem to be a solution for Knockout, but I don't know how to apply it to AngularJS: http://stackoverflow.com/questions/16421463/handle-ie-9-10s-clear-button-with-knockout-binding/ – dprothero Feb 20 '15 at 21:29
  • Lach: This is a really good workaround, thank you. Not marking as answer yet until I confirm there isn't a way to make the X button actually work. It worked in AngularJS 1.2.1 and broke in 1.3.6. – dprothero Feb 20 '15 at 22:10
  • Yeah, but why waste time trying make things work only on IE, when you can quickly write a directive, that works on all browsers. – Michał Lach Feb 21 '15 at 09:04
  • I hate to have to do this but until Angular fixes this bug, this is a good solution. – duyn9uyen Jun 05 '15 at 18:47
  • 1
    To be honest, I don`t see how this is related to Angular.js. It is native IE11 behaviour. – Michał Lach Jun 06 '15 at 12:08
  • 1
    Keep it simple. Just hide it. Don't hack something, so angular start to react to this kind of event, because there is no real value your user gains. – Denis.Sabolotni Nov 15 '18 at 12:06
7

I created this Angular directive for input text elements, which manually calls the element's change() event when the clear ('X') button is clicked. This fixed the problem on our project. I hope it helps others.

angular.module('app')
    .directive('input', function () {
        return {
            restrict: 'E',
            scope: {},
            link: function (scope, elem, attrs) {

                // Only care about textboxes, not radio, checkbox, etc.
                var validTypes = /^(search|email|url|tel|number|text)$/i;
                if (!validTypes.test(attrs.type)) return;

                // Bind to the mouseup event of the input textbox.  
                elem.bind('mouseup', function () {

                    // Get the old value (before click) and return if it's already empty
                    // as there's nothing to do.
                    var $input = $(this), oldValue = $input.val();
                    if (oldValue === '') return;

                    // Check new value after click, and if it's now empty it means the
                    // clear button was clicked. Manually trigger element's change() event.
                    setTimeout(function () {
                        var newValue = $input.val();
                        if (newValue === '') {
                            angular.element($input).change();
                        }
                    }, 1);
                });
            }
        }
    });

With thanks to this answer (Event fired when clearing text input on IE10 with clear icon) for the JavaScript code to detect the clear button click.

Community
  • 1
  • 1
raggle
  • 106
  • 1
  • 3
0

I was able to solve this using the following directive - derived from 0x783e's answer above. It may provide better compatibility with later versions of angular. It should work with $watches or parsers in addition to ng-change.

angular
    .module('yourModuleName')
    .directive('input', FixIEClearButton);

FixIEClearButton.$inject = ['$timeout', '$sniffer'];

function FixIEClearButton($timeout, $sniffer) {
    var directive = {
        restrict: 'E',
        require: '?ngModel',
        link: Link,
        controller: function () { }
    };

    return directive;

    function Link(scope, elem, attr, controller) {
        var type = elem[0].type;
        //ie11 doesn't seem to support the input event, at least according to angular
        if (type !== 'text' || !controller || $sniffer.hasEvent('input')) {
            return;
        }

        elem.on("mouseup", function (event) {
            var oldValue = elem.val();
            if (oldValue == "") {
                return;
            }

            $timeout(function () {
                var newValue = elem.val();
                if (newValue !== oldValue) {
                    elem.val(oldValue);
                    elem.triggerHandler('keydown');
                    elem.val(newValue);
                    elem.triggerHandler('focus');
                }
            }, 0, false);
        });

        scope.$on('$destroy', destroy);
        elem.on('$destroy', destroy);

        function destroy() {
            elem.off('mouseup');
        }
    }
}
Tim Mac
  • 1,149
  • 1
  • 8
  • 17
0

While hiding using CSS Instead of 'type=text' use 'type=search' in search fields.By doing this only inputs marked as 'type=search' will not have 'X' but other inputs will still have 'X' which is required on many other fields in IE.

input[type=search]::-ms-clear {
   display: none;
}
Sun
  • 11
  • 1
0
<input type="text" ng-model="name" id="search" />

This solution works for me

$("#search").bind("mouseup", function(e){
  var $input = $(this),
      oldValue = $input.val();

  if (oldValue == "") return;

  // When this event is fired after clicking on the clear button
  // the value is not cleared yet. We have to wait for it.

  setTimeout(function(){

    var newValue = $input.val();
    if (newValue == ""){
$scope.name="";
$scope.$apply();

    }
  }, 1);

});
Shubham Tiwari
  • 128
  • 1
  • 6
-1

The solution I came up with, while doesn't update the model immediately like removing the X and implementing you own solution, It does solve for what i needed. All I did was add ng-model-options to include blur. So when the input is blurred it will update the scope value.

<input type="text" ng-model="name" ng-model-options="{ updateOn: 'default blur'}"  />
Delta
  • 869
  • 6
  • 12
  • It has not worked for me. I've build a wrapper around the native input element and added this directive but the model was not updated at all. – Denis.Sabolotni Nov 15 '18 at 11:23