Listening to ngModel in a directive

It took a bit of searching until I found the solution to how one can listen to ng-model changes in a directive with isolate scope. The suggestive solution would be to add a listener to the $viewChangeListeners property of the ngModel controller. But this isn’t failsafe, it seems; the listeners aren’t called for all changes.

So a $watch on the scope it is… But what should we be listening to? Where is the model value to be found?

The answer is that the model value is passed as the argument of the ng-model attribute. So the trick is to include this in the directive’s scope and then add the $watch.

That may sound difficult, but the following example code should clear things up.


<html ng-app="selectingApp">
    <meta charset="UTF-8">
<body ng-controller="MainCtrl as ctrl">
<select ng-options="c for c in ctrl.colors track by c" ng-model="ctrl.color" note-selection></select>
<button ng-click="ctrl.changeColor()">Change!</button>
<script src=""></script>
    angular.module('selectingApp', [])
            .controller('MainCtrl', [function() {
                                var self = this;

                                self.colors = ['red', 'green', 'blue'];

                                self.changeColor = function() {
                                    self.color = 'green';
            .directive('noteSelection', [function() {
                               return {
                                   restrict: 'A',
                                   require: 'ngModel',
                                   scope: {
                                       model: '=ngModel'
                                   link: function($scope, $element, $attr, ngModelCtrl) {
                                       $scope.$watch('model', function() {
                                           console.log('Model has changed to ' + $scope.model);

Read more