Access to custom filter from an Angular directive with isolate scope

Al R. picture Al R. · Oct 9, 2013 · Viewed 13.1k times · Source

I've defined a custom filter and a directive with an isolate scope and I can't figure out why the directive has access to the custom filter when I haven't injected it into the directive module (I have injected it into the application module--see example).

Are scoping rules for filters different than for other scope properties? Or is this the wrong framework to use when thinking about filters?

Working example here: http://jsbin.com/IRogUxA/6/edit?html,js,output

Thanks in advance!

Answer

Adam Thomas picture Adam Thomas · Oct 9, 2013

This is because the directive is a child of the root scope created by the exampleApp module. The services, controllers, and directives modules are injected into exampleApp giving prototypical inheritance up the tree from child to root scope. It is dangerous to rely on the toDate filter being accessible to the linkBox directive in case at some point in the future the root scope created by exampleApp were to exclude the services module.

What Erstad Stephen wrote in his answer is partially correct, but his example won't work as it is typed since the $injector requires filter names to have a suffix of Filter. As is detailed in the $filterProvider docs.

The following code works:

//CORE MODULE
angular.module('exampleApp',['controllers','directives']);

angular.module('controllers',[]).controller('app_ctrl',['$scope',function($scope){
  $scope.dateVal = 20131010;
}]);

angular.module('services',[]).filter('toDate',[function(){
  function func(ymd){
    ymd = ymd + "";
    var y = ymd.substring(0,4);
    var m = ymd.substring(4,6);
    var d = ymd.substring(6);
    return (+m) + "/" + (+d) + "/" + y;
  }
  return func;
}]);

//DIRECTIVE
angular.module('directives',['services']).directive('linkBox', ['toDateFilter', function(toDate){
  var dir = {
    transclude:false,
    scope:{isolateVar:'@linkBox'},
    replace:true,
    template:'<p>Filtered value: {{isolateVar | toDate}}</p>',
    link: function lfn(scope, instance, attr){
      var a = angular.element(instance); 
      a.text(scope.isolateVar.name);
      console.log(scope);
    } //end link function
  }; //end dir object
  return dir;
}]);

Here's the working JSBin: http://jsbin.com/ICUjuri/2/edit