Hello!
From my perspective, your best bet is to use $observe:
$attrs.$observe( 'test', function( val ) {
if ( ! angular.isDefined( val ) ) {
$scope.test = 'Hello';
}
});
The controller method only gets executed once; $observe will get executed on each interpolated change. This will allow you to react to values that were once defined and have become undefined or were once populated and are now blank, etc.
Also, the controller is executed *before* the attributes are interpolated, so it will always be undefined when your controller runs. What's actually happening here is that you're assigning a scope property that just never gets overwritten by a new value because one wasn't provided. If you wanted more complicated logic (like validation) then you couldn't use that method at all.
There's also the added benefit that this method will work seamlessly without the isolate scope magic, so we can follow the same pattern in child scope directives. We only need one trick in the bag:
$attrs.$observe( 'test', function( val ) {
$scope.test = angular.isDefined( val ) ? val : 'Hello';
});
Josh