Luckylooke
Luckylooke

Reputation: 4539

Moving child directive from template to compile fn breaks scope connections

I have nested directives, both creates new scopes. To preserve original content I decide to move child directive to compile function of parent directive. This move breaks connection between scopes, could someone explain me why? Thanks

jsfiddle: (remove template from parent directive to see the issue) http://jsfiddle.net/luckylooke/uDkd3/9/

var myApp = angular.module('myApp', [])
.directive('parent', function directive() {
return {
    compile: function(elm){
        elm.append("</br> Appended <div child></div>");
    },
    template:"</br>From template <div child></div>",
    scope: {},
    controller: function ($scope) {
        $scope.who = "parent";
        $scope.message = "Text message";
        //console.log($scope);
    }
};
}).directive('child', function directive() {
return {
    replace: true,
    scope: {},
    template: '<div class="child">child with {{$parent.message || "NO message!"}}</div>',
    controller: function ($scope) {
        $scope.who = "child";
        //console.log($scope);
    }
};
});

Upvotes: 1

Views: 688

Answers (1)

Marc Kline
Marc Kline

Reputation: 9409

The Problem

As per this answer in Angularjs isolated scope for directives without own template:

[...] only elements in a template for the directive will be bound to the isolated scope created by that directive. If you don't use a template - content of the element, on which the directive is declared, will bind as if isolated scope was not there.

Here is what your scope hierarchy looks like with a template:

enter image description here

... and here is what it looks like without one:

enter image description here

A Solution

Use transclusion to inject elements from your view into parent without using compile:

.directive('parent', function directive() {
  return {
      transclude: true,
      template:"</br><div ng-transclude></div>From template <div child></div>",
      scope: {},
      controller: function ($scope) {
          $scope.who = "parent";
          $scope.message = "Text message";
      }
  };
})

Demo

Here the child directive is again an actual child of the parent directive. Notice too that the transcluded content appears in another scope which is a sibling of parent's isolate scope:

enter image description here

Upvotes: 1

Related Questions