0

I have written an AngularJS directive to validate percent value,

AngularJS Directive

app.directive('validatePercent', function () {
    return {
        restrict: 'A',
        link: function ($scope, elem, attr) {
            $scope.$watch(function () { return elem.val(); },
                function (newVal, oldVal) {
                    console.log("old : ", oldVal);
                    console.log("new : ", newVal);
                    if (newVal < 0 || newVal > 100)
                    {
                        elem.val(oldVal);
                    }
                }
            );
        }
    };
});

Here's my HTML

<input validate-percent ng-model="obj.progress" type="number" class="form-control" />

Note : obj.progress is of type int, also input type is number

The issue is when I try to change value of this input field multiple times quickly one after the another value goes to -1 or even 101 sometimes. Although condition in my directive is newVal < 0 || newVal > 100

Need help.

UPDATE 1:

This happens only when user changes values using mouse wheel. It doesn't happens while increment or decrements by arrow keys on keyboard.

Yogesh
  • 1,565
  • 1
  • 19
  • 46
  • Why not use `` – yeouuu Mar 30 '16 at 13:00
  • because min and max are not recognized by all browsers. I guess Firefox is one of them. – Yogesh Mar 30 '16 at 13:07
  • 1
    Min-max is working for me in the latest Firefox. But anyway you don't need a watcher for this. You can do it with validators: http://stackoverflow.com/questions/12581439/how-to-add-custom-validation-to-an-angularjs-form – yeouuu Mar 30 '16 at 13:13
  • another reason for not using min max is, if a user enters something like -236 then it accepts that value, even if min is set to 0 – Yogesh Mar 30 '16 at 13:25
  • No your form will be invalid. You should look into angular form validation. This answer is not the correct way to handle this. – yeouuu Mar 30 '16 at 13:36

1 Answers1

2

Instead of using $watch, you can handle it using focus/blur events.

app.directive('validatePercent', function () {
    return {
        restrict: 'A',
        link: function ($scope, elem, attr) {
            var oldVal = elem.val();
            elem.bind('focus', function(e) {
                oldVal = elem.val();
            });
            elem.bind('blur', function(e) {
                if ( elem.val()< 0 || elem.val() > 100)
                {
                    elem.val(oldVal);
                }
            });
        }
    };
});

Hope it helps.

Thomas Bormans
  • 5,156
  • 6
  • 34
  • 51
Subash Selvaraj
  • 3,385
  • 1
  • 14
  • 17