0

I have a setup like this:

var myApp = angular.module('myApp', []);

myApp.controller('MyCtrl', function() {});

myApp.directive("grandParent", function() {
 return {
  template: [
   '<div style="border: 1px solid">',
    '<p>transcluded view is below:</p>',
    '<ng-transclude></ng-transclude>',
   '</div>'
  ].join(""),
  transclude: true,
  controller: function() {
   this.getMe = "grandParentCtrl.controller.getMe";
  }
 };
});

myApp.directive('parent', function($compile) {
 return {
  require: "^^grandParent",
  link: function($scope, $element, $attrs, grandParentCtrl) {
   $element.append($compile('<son></son>')($scope, undefined, {
    transcludeControllers: {
     grandParent: {
      instance: grandParentCtrl
     }
    }
   }));
  }
 }
});

myApp.directive('son', function($compile) {
  return {
    require: '^^grandParent',
  template: [
   '<div class="btn btn-danger">',
    'abc: <i>{{abc}}</i>',
   '</div>'
  ].join(""),
  link: function(scope, element, attrs, ctrl) {
   scope.abc = ctrl.getMe;
  }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl as vm">
  <grand-parent>
  <parent></parent>
  </grand-parent>
</div>

(grand-parent directive has parent directive. The parent directive $compiles son directive)

In the directive son, if I require: "^^grandParent" it gives an error saying

"grandParent" directive required by "son" directive cannot be found

BUT, if in son I write require: "^grandParent" (*using ^ instead of ^^) it works.

If we look at the resulting HTML, it looks like this:

<grand-parent>
  <parent>
    <son>
    </son>
  </parent>
</grand-parent>

Obviously, grand-parent is strictly an ancestor of son. So why the error?

1 Answers1

-1

grandParent -> Add controllerAs:'grandParent'.

son -> replace require: '^^grandParent' with '^grandParent'.


JS:

        var myApp = angular.module('myApp', []);

        myApp.controller('MyCtrl', function() {});

        myApp.directive("grandParent", function() {
            return {
                template: [
                    '<div style="border: 1px solid">',
                        '<p>transcluded view is below:</p>',
                        '<ng-transclude></ng-transclude>',
                    '</div>'
                ].join(""),
                transclude: true,
                controller: function() {
                    this.getMe = "grandParentCtrl.controller.getMe";
                },
            controllerAs: 'grandParent'
            };
        });

        myApp.directive('parent', function($compile) {
          return {
                require: "^^grandParent",
            link: function($scope, $element, $attrs, grandParentCtrl) {
              $element.append($compile('<son></son>')($scope, undefined, {
                        transcludeControllers: {
                            grandParent: {
                                instance: grandParentCtrl
                            }
                        }
                    }));
            }
          }
        });

        myApp.directive('son', function($compile) {
          return {
            require: '^grandParent',
                template: [
                    '<div class="btn btn-danger">',
                        'abc: <i>{{abc}}</i>',
                    '</div>'
                ].join(""),
            link: function(scope, element, attrs, ctrl) {
                    scope.abc = ctrl.getMe;
                }
          };
        });

Wanna know how I did it - check the updated fiddle :-):

Community
  • 1
  • 1
Mahesh
  • 954
  • 8
  • 18
  • The OP already knows this. They want to know *why* this is happening. – Makoto Oct 25 '16 at 16:05
  • He doesn't. By saying "BUT, if in son I write require: "^grandParentCtrl" (*using ^ instead of ^^) it works.", the OP makes it look like *this is one way of doing it*, but unfortunately, *that* doesn't work. Replacing wtih`require:'^grandParentCtrl'` in son still will give error. I would suggest that the OP be clear on what works and what don't work. Then we can bridge the gap. This seems to be a very hypothetical question rather than one that is real. Correct me if I am wrong. There are lots of material that gives difference between require with ^ and ^^ out there. – Mahesh Oct 25 '16 at 16:10
  • There's...no hypotheticals here. The OP is aware of what will make their code work; what they're looking for is an understanding as to why their code doesn't work in its current state. – Makoto Oct 25 '16 at 16:16
  • OP does not know it. The OP's suggestion of he/she can make it work does not work. [Look at this fiddle - https://jsfiddle.net/newjavaonemahesh/rfL6rs6m/](https://jsfiddle.net/newjavaonemahesh/rfL6rs6m/). The change the OP claims to have done to make it work, does not work. Using ^grandParentCtrl will not work, no matter what. – Mahesh Oct 25 '16 at 16:17
  • @Mahesh no I do know it. I said it in my question, as @Makoto pointed out. I think you got hang up on a typo I did which I have now fixed. I'm aware I can write `"^grandParent"` instead of `"^^grandParent"` and make it work but it just doesn't make sense to me. –  Oct 26 '16 at 07:29
  • well, then you should also know that when you include transcluded content, it is not a descendant, but only added as a sibling. Just that these types of brainteasers which are used in online interviews doesn't seem real to me, and why would anyone has to answer it. If that is not the case, then you must be brilliant for you could code this much, not knowing about transclusion. And for the record, more correct explanation are found in this [Wonderful SO POST](http://stackoverflow.com/questions/16653004/confused-about-angularjs-transcluded-and-isolate-scopes-bindings) – Mahesh Oct 27 '16 at 13:22
  • As mentioned in the [Wonderful SO POST](http://stackoverflow.com/questions/16653004/confused-about-angularjs-transcluded-and-isolate-scopes-bindings), since Angular1.3+, you have transclusion as child of the directive's isolated scope, but unfortunately you are not defining isolate scope, so that is ruled out. – Mahesh Oct 27 '16 at 13:23
  • @Mahesh well it's just trial and error. Transclude etc are relatively easy and they are not the source of the problem anyway. The $scope hierarchy or transclude are clearly innocent, as you can see from here: https://jsfiddle.net/36e6z2c4/6/ . This is a $compile problem. –  Nov 02 '16 at 08:56