How can an Angular directive compile() function access an isolated scope?

11,097

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.

Share:
11,097
ehmicky
Author by

ehmicky

Updated on June 26, 2022

Comments

  • ehmicky
    ehmicky about 2 years

    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.