访问指令控制器的最佳模式

时间:2014-02-10 13:50:28

标签: javascript angularjs angularjs-directive

“form aka ngForm”指令可以通过表单名称加入。

<form name="testForm"> </form>

然后在控制器中我们可以这样做:

$scope.testForm.$valid 

在HTML中:

<button ng-show="testForm.$valid>

这使得“form”指令真的是一个具有可访问属性和方法的UI组件(就像在非html世界中一样)

是否有一种标准方法可以为自己的指令实现这种组件化?例如,我希望拥有所有方法的指令“list”,如“selectElement”,“scrollToTop”,“scrollToElement”,“doSomething”等,并像这样使用

<list name="myList></list>

<button ng-click="myList.doSomething()">

和其他一些控制器:

$scope.myList.scrollToTop();

我根据“form”指令做了一些简单的黑客攻击 - 它在name属性定义的变量范围内发布指令的public api:

app.directive('list', function () {
        return {
            restrict: 'E',
            controller: function ($scope, $element, $attrs) {

                // check if name of component does not pollute scope
                if ($attrs.name) {
                    if (angular.isDefined($scope[$attrs.name])) {
                        throw "Error component already defined with name: " + $attrs.name;
                    } else {

                      // publish controller object aka public API

                      scope[$attrs.name] = {
                               date: new Date(), 
                               myFunction: function(){}
                      };
                    }
                }
            },
            template: '<ul></ul>'
        }
    });

所以:

<list name="myList"></list>
<button ng-click="myList.myFunction()">

$scope.myList.myFunction();

但是它没有使用隔离范围指令 - 解决方法是将api对象作为具有双向绑定的属性传递,如此问题:How to call a method defined in an AngularJS directive?

我还考虑过在服务中定义api但它确实很难看 - 服务必须以某种方式 附加到指令的正确DOM元素。

所以我的问题是 - 从HTML和其他控制器访问指令方法和属性的最佳模式是什么,使指令成为真正的UI组件?

或者更简单的问题 - 如何从另一个控制器或HTML中的另一个表达式访问指令控制器,就像我们可以通过“require”从另一个指令那样。

2 个答案:

答案 0 :(得分:0)

您应该使用指令控制器并通过controllerAs发布它。 watch this

答案 1 :(得分:0)

即使作用域是隔离的,它仍然具有指向父作用域的$parent属性。因此,对于您的问题,解决方案可能如下所示:

angular.module('sample', []).directive("foo", function() {
  return {
    controller: function($scope, $element, $attrs) {
      $scope.$parent[$attrs.foo] = this;
      this.apiMethodName = function() {
          // ...
      };
    },
    scope: {},
    restrict: 'A'
  };
});

在Plunker上试试:http://plnkr.co/edit/qmGcAY?p=preview