AngularJS传递并使用外部控制器

时间:2016-07-13 12:10:49

标签: javascript angularjs

总之,我有下一个问题:

如何正确地将控制器传递给指令并在transclude块中使用它。

我想要的是让指令用户有机会在transclude块中使用某个特定的控制器。实现一些不同指令用法不常见的特定操作的目的。

我相信可以将控制器作为属性发送,然后以某种方式将其字段添加到链接功能中的范围,但我看不到正确的方法。

我目前的尝试是下一步。 基础html:

    <mylist items="list" ctrl="internalCtrl1">
      <li>
        {{element}} <a ng-click="showAbc()">ShowAbc</a>
      </li>
    </mylist>
    <h3>List2</h3>
    <mylist items="list" ctrl="internalCtrl2">
      <li>
          {{element}} <a ng-click="showXyz()">ShowXyz</a>
      </li>
    </mylist>

指令:

<div>
  <p>Cool list</p>
  <!--<ul ng-controller="ctrl">-->
  <ul>
    <ng-transclude></ng-transclude>
  </ul>
<div>

指令脚本:

    ......... 
    scope: {
      ctrl: "=",
      items: '='
    },
    controller: function($scope){
      //some common stuff
    },
    link: function($scope, $element, $attrs, controller, $transclude) {
      $scope.$watch("items", function(items) {

        var el = $element.find("ul");
        el.empty();

        if(items)
          items.forEach(function(item) {
            var childScope = $scope.$new();
            childScope.element = item;

            $transclude(childScope, function(content) {
              el.append(content);
            });

          });

      });
    }

完整代码:here

非常感谢任何帮助。

更新。我现在有2个问题:

  • 当我在指令中使用传递的控制器时 - 我得到错误'ctrl'是 不是一个功能
  • 当我在指令中使用固定控制器时 - 没有 从transclude block
  • 访问控制功能

1 个答案:

答案 0 :(得分:1)

我认为这就是你想要的......

.directive('mylist', function($controller){
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    templateUrl: 'mylist.html',
    scope: {
      ctrl: "@",
      items: '='
    },
    controller: function($scope){
      //some common stuff
    },
    link: function($scope, $element, $attrs, controller, $transclude) {
      $scope.$watch("items", function(items) {

        var el = $element.find("ul");
        el.empty();
        if(items)
          items.forEach(function(item) {
            var childScope = $scope.$new();
            childScope.element = item;
            var theCtrl = $controller($scope.ctrl, {
              $scope: childScope
            });

            $transclude(childScope, function(content) {
              el.append(content);
            });

          });

      });
    }
  };
})

https://plnkr.co/edit/7CFcOAB8HjeGARtq3K1t?p=preview

注意我将你的ctrl绑定更改为“@”,因为你真的只想要控制器的名称。然后在链接中使用$ controller对象实例化控制器并传递新创建的子范围。它将在实例化期间将控制器的方法添加到childScope。

编辑:

根据您的意图,您可能希望采用不同的方法。也许您应该将“智能”表分解为多个指令。一个可以是根,一个可以是行。该行可以具有函数绑定'&',例如on-select="myCtrl.selectItem(item)",用户可以执行以下操作:

<smart-table items="items" on-paginate="paginateHandler()">
  <smart-table-row on-select="selectHandler(item)" ng-repeat="item in items"></smart-table-row>
</smart-table>