Regarding AngularJS directives I've ran into a situation where I'm calling a directive from within another directive and I have the following questions.
All of the below can be seen at http://jsfiddle.net/sdg9/AjDtt/13/
HTML:
<directive bind-value="12" value="7"></directive>
JS:
var myApp = angular.module('myApp', []);
var commonTemplate = '<div>{{name}} bind-value is: {{bindValue}} </div><div>{{name}} value is: {{value}} </div><div>{{name}} add one to bind-value is: {{addOneBindValue}} </div><div>{{name}} add one to value is: {{addOneValue}} </div><br/>';
myApp.directive('directive', function () {
return {
scope: {
bindValue: "@",
},
template: commonTemplate + '<br/><sub-directive bind-value="{{value}}" value="{{value}}"></sub-directive>',
restrict: 'E',
link: function (scope, element, attrs) {
scope.name = "Directive";
scope.value = attrs.value;
scope.addOneBindValue = parseInt(scope.bindValue) + 1;
scope.addOneValue = parseInt(scope.value) + 1;
}
};
});
myApp.directive('subDirective', function () {
return {
scope: {
bindValue: "@"
},
template: commonTemplate,
restrict: 'E',
link: function (scope, element, attrs) {
scope.name = "SubDirective";
scope.value = attrs.value;
scope.addOneBindValue = parseInt(scope.bindValue) + 1;
scope.addOneValue = parseInt(scope.value) + 1;
}
};
});
Output:
Directive bind-value is: 12
Directive value is: 7
Directive add one to bind-value is: null <--- why?
Directive add one to value is: 8
SubDirective bind-value is: 7
SubDirective value is: <--- why?
SubDirective add one to bind-value is: null
SubDirective add one to value is: null
Interpolated attributes (i.e., attributes that use {{}}s) and isolate scope properties defined with '@' are not available when the link function runs. You need to use attrs.$observe() (or scope.$watch( @ property here, ...)) to get the values (asynchronously).
So, scope.bindValue is not available when you are trying to use it.
Similarly, in your subDirective, attribute value has {{}}s, so its value will also not be available when you are trying to use it. You also need to define an '@' directive property for this.
Working fiddle.
The reason for the asynchronous requirement is that the items inside the {{}}s may change, and you normally want your directive to notice (and then do something -- like update the "addOne" values). '@' is normally used with isolate scopes when the attribute value contains {{}}s.
If attribute values are constants, and you're not going to use the values in a template (or templateUrl), then '@' probably shouldn't be used. In the link function, just use attrs.attrName if the value is a string, or scope.$eval(attrs.attrName) if the attribute is a number or boolean (or parseInt(attrs.attrName) if you know it is a number).