Nesting directives within directives

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.

  1. Why can't I referecne scope.bindValue in my link function? Is there a way I can compute a value from scope.bindValue and set it to scope?
  2. Why can the subdirective bind using "@" in scope:{} but not use scope.value = attrs.value in the link function?

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).