Usage:
<my-directive my-var="true"></my-directive>
Directive:
app.directive('myDirective', [
function () {
var definition = {
restrict: "E",
replace: false,
transclude: false,
scope: {
myVar: '@',
},
controller: ['$scope', function($scope) {
console.log($scope.myVar); // "true"
$scope.myVar = "false";
console.log($scope.myVar); // "false"
setTimeout(function() {
console.log($scope.myVar); // "true" (!)
}, 100);
}]
};
return definition;
}
]);
Console output
"true"
"false"
"true"
What is exactly happening here? The variable is passed as string ("true"), I'm changing it, then it get's replaced again? I would like to understand the cycle here. Is this because there is some additional compilation or digest cycle kicking in and recalculating all isolated scope values again? I thought that once set, variables passed like this (@, just string in directive) would stay the same?
Is there any way to hook up within directive to a moment, after which string variables are not replaced, or will it always work like this with every digest or whatnot, and I'm forced to use $watch?
@
binds the parent scope to the isolated scope and it's a one-way (not one-time) binding. So, any change in the outer scope will reset the value in the directive's isolate scope.Under the covers, Angular calls
attrs.$observe
on the element attribute with "@". What this does is that it queues an observer function for the next $digest cycle after the compilation. That observer function is what sets the scope variable every time there is a change in the interpolated value assigned to the attribute.So, the high-level steps are:
So, given this, you can now see why your change didn't persist. It would, if you made it after all of these steps - i.e. with a timeout or in response to an event. And only if the attribute interpolated value hasn't changed.
This is NOT so with "
=
".Here's a plunker illustrating the differences.
If you want a one-time passage of variables, just set the scope variable using an attribute in the link function or the controller
and remove
myVar
from the scope.