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.

5
  • Why not use <input type="number" ng-model="obj.progress" min="0" max="100"> Commented Mar 30, 2016 at 13:00
  • because min and max are not recognized by all browsers. I guess Firefox is one of them. Commented Mar 30, 2016 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: stackoverflow.com/questions/12581439/… Commented Mar 30, 2016 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 Commented Mar 30, 2016 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. Commented Mar 30, 2016 at 13:36

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Nice solution. This also solved my other problem, maintaining old value. ;). Thanks.
@Yogesh, Glad it helped. Accept my answer please.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.