0

I have two nested directive and a few controllers and I want inject controller to second controller.

When I bind action to some button it work but list don't show up, some one know why?

Dynamic Controller directive

.directive("dynamicController", ["$compile", function($compile) {
    return {
      restrict: "A",
      scope: {
        dynamicController: "@"
      },
      compile: function(tElement, tAttrs) {
        return {
          pre: function preLink(scope, iElement, iAttrs, controller) {
            iElement.attr("ng-controller", scope.dynamicController);
            iElement.removeAttr("dynamic-controller");
            $compile(iElement)(scope);
          }
        }
      }
    }
  }])

V1: http://codepen.io/anon/pen/LVeaWo
V2: http://codepen.io/anon/pen/EjoJVx

[ EDIT ]

I almost do it but it's one more problem. I have two directive:

.directive("wrapDirective", function() {
    return {
      restrict: "A",
      template: "<div dynamic-controller=\"Ctr1\">" +
        "<button ng-click='action()'>Click</button>" +
        "<ul>" +
        "<li ng-repeat=\"item in list\">{{item}}</li>" +
        "</ul>" +
        "</div>",
      scope: {
        controller: "@wrapDirective"
      }
    }
  })

and

.directive("dynamicController", function($compile) {
    return {
      restrict: "A",
      scope: true,
      controller: "@",
      name: "dynamicController"
    }
  })

The problem is this line <div dynamic-controller=\"Ctr1\"> in warpDirective

I can't do something like this <div dynamic-controller=\"{{controller}}\">

CodePen with both cases: http://codepen.io/anon/pen/EjoJXV

Alcadur
  • 681
  • 1
  • 8
  • 22

3 Answers3

1

You should use require and link to get the controllers of parent directives. See Creating Directives that Communicate.

.directive('myDirective', function() {
  return {
    require: '^ngController', // <-- define parent directive
    restrict: 'E',
    scope: {
      title: '@'
    },
    link: function(scope, element, attrs, ctrl) { // <-- get the controller via the link function
      ctrl.doSomething();
    }
  };
Michael
  • 3,085
  • 1
  • 17
  • 15
0

The reason behind your code is not working is, {{}} interpolation value is not evaluated in you pre link function. So by compiling ng-controller with not value in it is throwing an error. You should use iAttrs.$observe as you are evaluating expression inside {{}}.

Code

var dynamicControllerObserver = iAttrs.$observe('dynamicController', function(newVal, oldVal) {
    wrapElement.attr("ng-controller", scope.dynamicController);
    wrapElement.append(iElement.html());
    console.log(wrapElement)
    iElement.html("");
    console.log(iElement)
    iElement.append(wrapElement);
    $compile(wrapElement)(scope);
    dynamicControllerObserver(); //destruct observe
})

Working Codepen

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • I don't know why but '$observe' don't work, I do that like this: http://codepen.io/anon/pen/EjoJVx but list still don't show up – Alcadur Jun 30 '15 at 08:24
0

I did it, really helpful was this post: Dynamic NG-Controller Name
I modified it to my needs:

.directive('dynamicCtrl', ['$compile', '$parse', function($compile, $parse) {
    return {
      restrict: 'A',
      terminal: true,
      scope: {
        dynamicCtrl: "@"
      },
      link: function(scope, elem, attr) {
        var initContent = elem.html();
        var varName = getName(elem.attr('dynamic-ctrl'));

        update();
        scope.$watch("dynamicCtrl", function() {
          update();
        })

        function update() {
          var wrapper = angular.element("<div></div>");

          wrapper.append(initContent);

          var name = $parse(varName)(scope.$parent);
          wrapper.attr('ng-controller', name);
          elem.empty();
          elem.append(wrapper);
          $compile(wrapper)(scope);
        }

        function getName(attr) {
          var startIndex = attr.lastIndexOf("{") + 1,
            endIndex = attr.indexOf("}");
          return attr.substring(startIndex, endIndex);
        }
      }
    };
  }])

http://codepen.io/anon/pen/xGYyqr

Community
  • 1
  • 1
Alcadur
  • 681
  • 1
  • 8
  • 22