AngularJS rewrites isolated scope
Using:
<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 exit
"true" "false" "true" What's going on here? Is the variable passed as a string ("true"), do I change it and then replace it again? I would like to understand this cycle here. Is it because there is another additional compilation cycle or digest cycle and recalculating all selected values ββof the scope again? I thought that once set variables passed like this (@, just a line in the directive) will remain the same?
Is there a way to connect inside the directive to the moment, after which the string variables will not be replaced or will it always work like this, with every digest or something else, and I have to use $ watch?
@ binds the parent region to an isolated region and is a one-way (not one-time) binding. Thus, any change in the external area will be reset to a value in the area of ββdirective allocation.
Under the covers , Angular calls the attrs.$observe element attribute using "@". This is because after compilation, it pauses the observer function for the next $ digest loop. This observer function is what sets the scope variable every time the interpolated value assigned to the attribute changes.
So, the high-level steps:
1) for `@` scope variable, set an observer function and queue it for later 2) set `@` scope variable to the interpolated value 3) run the controller, pre- and post-link functions ... N) observer runs against interpolated value and sets the scope value So, given this, you can now understand why your changes have not been saved. It would be if you did it after all these steps - that is, with a timeout or in response to an event. And only if the value of the interpolated attribute has not changed.
This is NOT so with " = ".
Here's a plunker illustrating the differences.
If you need a one-time pass of variables, just set the scope variable using the attribute in the link function or controller
scope.myVar = $attrs["my-var"]; and remove myVar from the scope.