Today I come across some really weird behavior in AngularJS using $ watch. I simplified my code in the following example:
https://jsfiddle.net/yLeLuard/
This example contains a service that will track the state variable. Directives are used to bind the click event to the DOM, which modifies the state variable through the service.
There are two problems in this example:
- The first close button (with the ng-click property on it) changes only the state on the second click
- Two buttons without ng-click do not change state at all
main.html
<div ng-controller="main"> State: {{ api.isOpen | json }} <div ng-click="" open> <button>Open - Working fine</button> </div> <div ng-click="" close> <button>Close - Works, but only on second click</button> </div> <div open> <button>Open - Not Working</button> </div> <div close> <button>Close - Not Working</button> </div> </div>
main.js
var myApp = angular.module('myApp', []); myApp.controller('main', ['$scope', 'state', function($scope, state) { $scope.api = state; $scope.api.isOpen = false; $scope.$watch('api.isOpen', function() { console.log('state has changed'); }); }]); myApp.directive('open', ['state', function(state) { return { restrict: 'A', scope: {}, replace: true, template: '<button>Open</button>', link: function(scope, element) { element.on('click', function() { state.isOpen = true; }); } }; }]); myApp.directive('close', ['state', function(state) { return { restrict: 'A', scope: {}, replace: true, template: '<button>Close</button>', link: function(scope, element) { element.on('click', function() { state.isOpen = false; }); } }; }]); myApp.service('state', function() { return { isOpen: null }; });
source share