Search code examples
javascriptangularjsjqlite

Passing jqLite .html() handle directly as an AngularJS watch listener


I'm trying to pass the jqLite function element.html directly as a listener of a watcher:

angular.module('testApp', []).directive('test', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      scope.$watch('someVariable', element.html); // <-- Passing the function handle as listener
    }
  };
});

However this does not work for some reason, so as a workaround I wrapped the listener in a function:

angular.module('testApp', []).directive('test', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      scope.$watch('someVariable', function (newValue) {
        element.html(newValue);
      });
    }
  };
});

This second example works.

I don't understand why the first example is broken. Any ideas?

EDIT: I forgot to mention, the browser does not give me any errors. It just shows me an empty element.


Solution

  • Actually, it's because of angular's injector that automatically changes the this property of a function, consider this:

    var test = function(string) {
        return {
            html: function(value) {
                console.log(this);
            }
        }
    }
    
    $scope.$watch('my_watch_expression', test('string').html);
    

    when you check the value of this, here is what you get:

    enter image description here

    As you can see, it will throw an error on the jQuery library:

    enter image description here

    this doesn't have an empty function, therefore, it will throw a silent exception and will not work as expected.