2
votes

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?

2
You need to make scope:true to get the parent scoperedconservatory

2 Answers

2
votes

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.

0
votes

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