动态控制器

时间:2015-06-30 06:19:47

标签: angularjs model-view-controller angularjs-scope

我有两个嵌套指令和一些控制器,我想将控制器注入第二个控制器。

当我将动作绑定到某个按钮时,它会工作,但列表不会显示,有人知道原因吗?

动态控制器指令

.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

[编辑]

我几乎要这样做,但这又是一个问题。 我有两个指令:

.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"
      }
    }
  })

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

问题是 warpDirective

中的这一行&lt; div dynamic-controller = \“Ctr1 \”&gt;

我不能做这样的事情&lt; div dynamic-controller = \“{{controller}} \”&gt;

CodePen包含两种情况:http://codepen.io/anon/pen/EjoJXV

3 个答案:

答案 0 :(得分:1)

您应该使用requirelink来获取父指令的控制器。 见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();
    }
  };

答案 1 :(得分:0)

您的代码背后的原因是{{}}插值不在您pre链接函数中评估。因此,通过编译ng-controller而没有值,它会引发错误。在评估iAttrs.$observe内的表达式时,应使用{{}}

<强>代码

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

答案 2 :(得分:0)

我做到了,这篇文章非常有用:Dynamic NG-Controller Name
我根据自己的需要修改了它:

.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