Boris B.
Boris B.

Reputation: 5024

Wrong scope when using $compile for a child directive

I need to conditionally use a child directive inside a parent directive.

I'm using $compile to compile a template for a child directive in parent directive's link function, and the child directive has its own isolated scope.

The problem is that an ng-click on the child directive is invoked in the parent scope when the child directive's element is clicked.

Here is an SSCCE:

var app = angular.module("test", []);

app.directive("parentDirective", function($compile) {
  return {
    restrict: "EA",
    scope: {},
    link: function(scope, element, attrs) {
      element.append('!');
      scope.foo = function() {
        alert('parent foo');
      };
      var childTemplate = "<div child-directive ng-click='foo()'>Child directive</div>";
      element.append($compile(childTemplate)(scope));
    }
  };
});

app.directive("childDirective", function() {
  return {
    restrict: "EA",
    scope: {},
    link: function(scope, element, attrs) {
      scope.foo = function() {
        alert('child foo!');
      };
      element.append('!');
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div ng-app="test">
  <div parent-directive>Parent directive</div>
</div>

The ng-click=foo() should invoke foo from the child scope, however it's invoking the parent foo. If you click Child directive! div you get Parent foo alert.

Why is that so and how can I make it work as expected?

Upvotes: 2

Views: 653

Answers (2)

Kalhan.Toress
Kalhan.Toress

Reputation: 21901

this issue is regarding scope of compiling the template.

check this PLUNKER

alert('init parent directive -1'); will called then the alert('init child directive'); and finally alert('init parent directive-2');

that means in line 20 in the plunker example, parent directive link function create a child-directive but the that directive compile against the parent directive scope not the scope of the child directive, so the $compile() can only see anything inside the parent directive scopecant see about the child scope.

if you need to attach child scope then you have to compile it inside the child directive. or better to use template or templateUrl in the child directive.

Upvotes: 2

Ajith Emalathas
Ajith Emalathas

Reputation: 41

var app = angular.module("test", []);

app.directive("parentDirective", function($compile) {
  return {
    restrict: "EA",
    template: "<div ng-click='foo()'>Parent directive!</div>", //You can use templateUrl as well
    scope: {},
    link: function(scope, element, attrs) {
      scope.foo = function() {
        alert('parent foo');
      };
      var childTemplate = "<child-directive/>";
      element.append($compile(childTemplate)(scope));
    }
  };
});

app.directive("childDirective", function() {
  return {
    restrict: "EA",
    template: "<div ng-click='foo()'>Child directive!</div>",
    scope: {},
    link: function(scope, element, attrs) {
      scope.foo = function() {
        alert('child foo!');
      };
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div ng-app="test">
  <parent-directive/>
</div>

Try this

Upvotes: 0

Related Questions