AngularJS how do I watch $viewValue instead of ngModel?

The docs have the answer: https://code.angularjs.org/1.2.19/docs/api/ng/type/ngModel.NgModelController

You want to use $viewChangeListeners instead of $watch like so (you might need to push to $formatters instead depending on how debounce works):

ngModelCtrl.$viewChangeListeners.push(function(){
  var val = parseInt(ngModelCtrl.$viewValue);
  if(!isNaN(val)) {
    ...
  }
});

Though I haven't played with the debounce option yet so I don't know if this will fix your problem, but this is how you watch the viewValue.


An alternative solution of watching the $viewValue is to allow invalid ng-model updates, then you can watch the model instead.

ng-model-options="{allowInvalid: true}"

see: https://docs.angularjs.org/api/ng/directive/ngModelOptions

It's not a direct answer to this question, but I think it will help in many of the usecases for which people are visiting this topic.


This will watch the $viewValue of a ngModelController if the tag has the ng-model and match attribute. It is also possible to watch other ngModelController $viewValues, like in a form with many input directives.

    (function () {
        'use strict';

        angular
            .module('app.commons')
            .directive('match', MatchValidator);

        function MatchValidator() {
            return {
                require: 'ngModel',
                link: LinkFunction
            };

            function LinkFunction(scope, element, attrs, ngModel) {
                scope.$watch(function(){
                        return ngModel.$viewValue;
                    }, 
                    function(newValue, oldValue){
                        // do something
                    }
                );
            }
        }
    })();