I do not understand what is going on with my $scope.isYellow
variable. Why it gets updated just fine but class yellow
isn't added to an element?
Here is a jsfiddle: http://jsfiddle.net/akctq645/
The goal is simple: when you click on a "Color" span
, it's background has to become yellow. I use ng-class
and a custom directive to achieve it. My custom directive's scope has appropriate variable isYellow
for that:
<span id="spanElem" make-yellow-directive ng-class="{yellow: isYellow}">Color</span>
controller: function($scope, $element, $attrs, $transclude) {
$scope.isYellow = 0;
this.toggleIsYellow = function() {
$scope.isYellow = ($scope.isYellow == 1) ? 0 : 1;
}
},
But whatever I do, it doesn't work. For some reason the variable $scope.isYellow
in this.toggleIsYellow
method gets updated but the span
doesn't become yellow, yellow
class is not added. Event if I toggle $scope.isYellow
manually in Chrome Console debugger, class yellow
doesn't appear on span
.
Why? What is going on? It is the same scope, it's isYellow
variable gets updated but why class yellow
isn't added to span
?
Angular's two-way binding is powered by the so called digest cycle. In short, Angular keeps its own event queue and uses it to figure out when it needs to walk the scope tree to check for changes. When you use the jQuery 'on()' function, you're creating an event that doesn't go through the Angular digest cycle, meaning that it won't know that it needs to update the ui to match changes in the scope. A quick fix would be to do this:
function onClickHandler(e) {
console.log('== onClickHandler ==: ', e);
scope.$apply(function () {
ctrl.toggleIsYellow(e);
});
};
The "$apply" method is used to force Angular to initiate a digest. Though, you should really just use "ng-click" on the span you want to have toggle behavior. Using "$apply" is usually a code-smell in Angular.