I have the following directive:
angular.module("example_module", [])
.directive("mydirective", function() {
return {
scope: { data: "@mydirective" }
compile: function(element) {
element.html('{{example}}');
return function($scope) {
$scope.example = $scope.data + "!";
};
}
};
});
and the following HTML code:
<!DOCTYPE html>
<html ng-app="example_module">
<head>
<meta charset="utf-8">
<title>Example title</title>
<script src="lib/angular/angular.min.js"></script>
<script src="js/example.js"></script>
</head>
<body>
<div mydirective="Hello world"></div>
</body>
</html>
I would expect the directive to compile to Hello world!
, but it compiles to an empty string instead. scope
creates an isolated scope which seems impossible to reach for {{example}}
.
I would like to know how the new HTML code created by compile()
can access the link function $scope
.
Isolated Scope In AngularJS. It can access its parent scope through the $parent property. So, Directive has three options for isolating its scope from parent scope. The following are the three options: scope: false - It is default in Directive. It lets to reuse the scope from the place where the component is being used.
This scope object is used for accessing the variables and functions defined in the AngularJS controllers, and the controller and link functions of the directive. By default, directives do not create their own scope; instead they use the scope of their parent, generally a controller (within the scope of which the directive is defined).
Isolating the scope in a directive is a simple process. Start by adding a scope property into the directive, as shown next. It automatically isolates the directive’s scope from any parent scope (s). The @ local scope property is used to access string values that are defined outside the directive.
For AngularJS, "compilation" means attaching directives to the HTML to make it interactive. The reason we use the term "compile" is that the recursive process of attaching directives mirrors the process of compiling source code in compiled programming languages. Matching Directives
This doesn't work because {{example}} is being evaluated against the parent scope, which makes sense, since you are essentially changing the element before compilation to:
<div>{{example}}<div>
You can verify by replacing '$scope.example =' with '$scope.$parent.example =' (for demonstration purposes only - it's not a best practice to use $parent).
What you are really trying to do is something similar to transclusion, but there are very easier ways to do it. For instance:
angular.module("example_module", [])
.directive("mydirective", function() {
return {
restrict: 'A',
scope: { data: "@mydirective" },
template: '{{example}}',
compile: function(element) {
return function($scope) {
console.log($scope.data);
$scope.example = $scope.data + "!";
console.log($scope.example);
};
}
};
});
When you use a template, it replaces the content of the element the directive is applied to (unless you use replace: true, in which case it replaces the entire element), and the contents of the template are evaluated against the directive scope.
You could do what you are trying to do using the transclude parameter passed to compile (see the docs), but this has been deprecated so I wouldn't recommend going down that road.
Here's a Plunk where you can play with some variations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With