3

I want to add a directive that will do something when an element class is changed.

My directive is:

(function (angular) {

angular.module('myApp')
    .directive('myClassWatch', myClassWatch);

function myClassWatch() {
    return {
        restrict: 'A',
        link: function (scope, element, attrs, controller) {
            scope.$watch(function () {
                return element.attr('class');
            }, function (newValue, oldValue) {
                debugger;
                if(oldValue !== newValue)
                    console.log('class changed from ' + oldValue + ' to ' + newValue);
            });
        }
    }
}
})(angular);

The html is:

<div class="top-icons-item popup-container popup-link-container" my-class-watch>

</div>

I do some actions elsewhere that toggles the class "open" in my div element - it is visible in the html - yet the debugger is never called (also no console logs of course). I can see that the link function is called on page load and the debugger also stops, but thats only on page load and not afterwards when I actually do actions that adds another class.

I have read several issued here before including Directive : $observe, class attribute change caught only once but I can't understand why I don't get the same result. What can I do to try check why this occures?

Update: The class change is made using jQuery not in a controller but in an old jquery watches code. May this be cause? could angular be unaware of class change when its not done from an angular code?

4
  • Have look on this stackoverflow.com/questions/31085553/… Commented Oct 10, 2016 at 8:57
  • You should use $observe and not $watch Commented Oct 10, 2016 at 8:57
  • But I read in the post that I added that observe will only work once. Commented Oct 10, 2016 at 9:01
  • I can't see why your code isn't working, see this working jsfiddle jsfiddle.net/cg0h5jgf Commented Oct 10, 2016 at 9:39

1 Answer 1

1

Wrap your jQuery code into $apply.

It similar to you are making changes to $scope out of angular context(jquery ajax, setTimeout, etc). Use $apply to make angular know about the changes done.

    angular.element(document.getElementById('app')).injector().invoke(['$compile', '$rootScope', function($compile, $rootScope) {
       $rootScope.$apply(function() {
           //your jquery code goes here...
           var a = document.getElementById('abc');
           angular.element(a).addClass('hello');
       });
    }]);
Sign up to request clarification or add additional context in comments.

2 Comments

No. You are externally triggers digest cycle to make angular known about your changes. It is similar to ng-click callback function. It also triggers digest cycle.
It also uses $apply internally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.