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!
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
This is because the filter is available to the 'exampleApp' module since it is a dependency.
Adam Thomas is correct about that, but it is a common scenario to depend on custom directives, services, and filters in other custom items. You want to make things explicit in your DI assertions. This will cause things to break at the injection level instead of when using the custom directive in this case.
//DIRECTIVE
angular.module('directives',['services']).directive('linkBox', ['toDate',function(toDate){
...
}]);
With this you can be clear about what you need to use the directive and will not be easily missed. This may require you to tweak how you declare 'toDate'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With