AngularJS - How do I know immediately when an input has been changed if it is debounced?

554 views Asked by At

Having a text input I want to know immediately when the user is changing the text, but also I want to use the debounce feature. This way I can, for example, disable a submit button while the user is changing the text and enable the submit button after checking the text in the debounced function.

Is there a way to do this with pure AngularJS? Or should I use javascript/jquery?

With this code I am only able to know when the user has changed the text after the debounce 500ms delay:

<!doctype html>
<html ng-app="app">
    <head>
        <script src="http://localhost/js/angular.min.js"></script>
        <script>
            var app= angular.module('app',[]);

            app.controller('ExampleController',['$scope',function($scope){
                $scope.changed= '';
                $scope.change= function(){
                    $scope.changed= 'Changed!';
                };
            }]);
        </script>
    </head>
    <body ng-controller="ExampleController">
        <div>Message: <input type="text" ng-model="model.message"
            ng-model-options="{debounce:500}" ng-change="change()" />

        <div>{{model.message}}</div>
        <div>{{changed}}</div>
    </body>
</html>
4

There are 4 answers

0
mGuv On

Your main option is to write your own debouncing code using ng-keyup. Every time a key is pressed, you will be notified of the change (and the change will be present in the ng-model value) and you can use your own setTimeout there, with the desired debounce function as the callback. If the timeout is already set, simply cancel it and restart it on each key press.

0
Michael On

Use $scope.$watch('model-name', function(){...}

0
TekTimmy On
angular.module('customControl').
directive('contenteditable', [function() {
return {
    restrict: 'A', // only activate on element attribute
    require: '?ngModel', // get a hold of NgModelController
    link: function(scope, element, attrs, ngModel) {
        if (!ngModel) return; // do nothing if no ng-model        
        ngModel.$parsers.push(function(value) {
            // do what you want to happen before "debounce"
            // debounce here by waiting 500ms
        });
    }
};
}]);

source: https://code.angularjs.org/1.4.1/docs/api/ng/type/ngModel.NgModelController

0
DrPollit0 On

Not being able to do this in a simple way I've finished doing it outside of angular with underscore library. That is the best option that I have found.

Here is my code:

<!doctype html>
<html ng-app="app">
    <head>
        <script src="http://localhost/js/angular.min.js"></script>
        <script src="http://localhost/js/underscore.js"></script>
        <script>
            var underscore= angular.module('underscore',[]);

            underscore.factory('_',function(){
                return window._; // assumes underscore has already been loaded on the page
            });

            var app= angular.module('app',['underscore']);

            app.controller('ExampleController',['$scope','_',function($scope,_){
                $scope.changed= '';

                $scope.change= function(){
                    $scope.debounceMessage($scope);
                };

                $scope.debounceMessage= _.debounce(function($scope){
                    $scope.$apply(function(){
                        $scope.changed= 'Delayed: '+$scope.model.message;
                    });
                }, 500);

            }]);
        </script>
    </head>
    <body ng-controller="ExampleController">
        <div>Message: <input type="text" ng-model="model.message"
            ng-change="change()" />

        <div>{{model.message}}</div>
        <div>{{changed}}</div>
    </body>
</html>

http://plnkr.co/edit/0gnwg9