从指令访问控制器范围

Mat*_*rts 19 angularjs isolate-scope

我创建了一个简单的指令,显示<table>我正在创建的排序列标题.

ngGrid.directive("sortColumn", function() {
    return {
        restrict: "E",
        replace: true,
        transclude: true,
        scope: {
            sortby: "@",
            onsort: "="
        },
        template: "<span><a href='#' ng-click='sort()' ng-transclude></a></span>",
        link: function(scope, element, attrs) {
            scope.sort = function () {

                // I want to call CONTROLLER.onSort here, but how do I access the controller scope?...
                scope.controllerOnSort(scope.sortby);
            };
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

以下是一些正在创建的表头的示例:

<table id="mainGrid" ng-controller="GridCtrl>
<thead>
    <tr>
        <th><sort-column sortby="Name">Name</sort-column></th>
        <th><sort-column sortby="DateCreated">Date Created</sort-column></th>
        <th>Hi</th>
    </tr>
</thead>
Run Code Online (Sandbox Code Playgroud)

因此,当单击排序列时,我想在我的网格控制器上触发onControllerSort函数..但是我被卡住了!到目前为止,我能够做到这一点的唯一方法是为每个<sort-column>添加"onSort"的属性并引用指令中的那些:

<sort-column onSort="controllerOnSort" sortby="Name">Name</sort-column>
Run Code Online (Sandbox Code Playgroud)

但这并不是很好,因为我总是想调用controllerOnSort,所以为每个指令管道都有点难看.如何在指令中执行此操作而不需要在HTML中使用不必要的标记?如果有帮助,指令和控制器都在同一模块中定义.

Jul*_*lzt 24

创建第二个指令作为包装器:

ngGrid.directive("columnwrapper", function() {
  return {
    restrict: "E",
    scope: {
      onsort: '='
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

然后你可以引用函数在outer指令中调用一次:

<columnwrapper onsort="controllerOnSort">
  <sort-column sortby="Name">Name</sort-column>
  <sort-column sortby="DateCreated">Date Created</sort-column>
</columnwrapper>
Run Code Online (Sandbox Code Playgroud)

在"sortColumn"指令中,您可以通过调用来调用该引用的函数

scope.$parent.onsort();
Run Code Online (Sandbox Code Playgroud)

看到这个小提琴的工作示例:http://jsfiddle.net/wZrjQ/1/

当然,如果你不关心硬编码的依赖关系,你也可以继续使用一个指令,只需调用父范围上的函数(那将是有问题的控制器)

scope.$parent.controllerOnSort():
Run Code Online (Sandbox Code Playgroud)

我有另一个小提琴显示:http: //jsfiddle.net/wZrjQ/2

该解决方案将有同样的效果(有关于硬耦合同样的批评),如其他答案溶液(/sf/answers/1357015621/),但至少比该解决方案比较容易.如果夫妻辛苦,无论如何,我不认为这是在引用,因为它最有可能是所有的时间可在$范围.$家长控制点(但其他元素建立一个范围提防).

不过,我会选择第一个解决方案.它增加了一些小标记,但解决了问题并保持了清晰的分离.如果您将第二个指令用作直接包装器,也可以确保$ scope.$ parent与外部指令匹配.

  • 虽然它在这里工作,但使用`$ parent`是一种糟糕的模式.它只能在更深层次上工作,因此很难重用. (2认同)

gm2*_*008 20

&local scope属性允许指令的使用者传入指令可以调用的函数.

&范围属性的插图

详情请见此处.

下面是一个类似问题答案,它显示了如何从指令代码传递回调函数中的参数.

  • 这里的详细信息链接非常丰富.谢谢! (4认同)

Nik*_*los 8

在您的指令中要求ngController并修改链接函数:

ngGrid.directive("sortColumn", function() {
    return {
        ...
        require: "ngController",
        ...
        link: function(scope, element, attrs, ngCtrl) {
            ...
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

你得到的ngCtrl是你的控制器,GridCtrl.你没有得到它的范围; 你必须做的事情:

xxxx.controller("GridCtrl", function($scope, ...) {
    // add stuff to scope as usual
    $scope.xxxx = yyyy;

    // Define controller public API
    // NOTE: USING this NOT $scope
    this.controllerOnSort = function(...) { ... };
});
Run Code Online (Sandbox Code Playgroud)

从链接函数中调用它简单如下:

ngCtrl.controllerOnSort(...);
Run Code Online (Sandbox Code Playgroud)

请注意,此要求将获得第一个父母ngController.如果GridCtrl在指令和指令之间指定了另一个控制器,您将获得该指令.

一个演示原理的小提琴(ng-controller用方法访问父节点的指令):http://jsfiddle.net/NAfm5/1/


人们担心这种解决方案可能引入不必要的紧耦合.如果这确实是一个问题,可以解决如下:

创建一个与控制器并排的指令,让我们调用它master:

<table id="mainGrid" ng-controller="GridCtrl" master="controllerOnSort()">
Run Code Online (Sandbox Code Playgroud)

该指令引用了控制器的所需方法(因此:解耦).

子指令(sort-column在您的情况下)需要master指令:

require: "^master"
Run Code Online (Sandbox Code Playgroud)

使用该$parse服务,可以从主控制器的成员方法调用指定的方法.查看实现此原则的更新小提琴:http://jsfiddle.net/NAfm5/3/