如何在angularjs指令中要求控制器

Edg*_*nez 84 javascript angularjs angularjs-directive

谁能告诉我如何在另一个angularJS指令中包含一个指令的控制器.例如,我有以下代码

var app = angular.module('shop', []).
config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/js/partials/home.html'
    })
        .when('/products', {
        controller: 'ProductsController',
        templateUrl: '/js/partials/products.html'
    })
        .when('/products/:productId', {
        controller: 'ProductController',
        templateUrl: '/js/partials/product.html'
    });
}]);

app.directive('mainCtrl', function () {
    return {
        controller: function ($scope) {}
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'C',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            //console.log(cartController);
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

从各方面来说,我应该能够在addProduct指令中访问控制器,但事实并非如此.有没有更好的方法呢?

Jos*_*ler 184

我很幸运并在对这个问题的评论中回答了这个问题,但为了完整起见,我发布了一个完整的答案,所以我们可以将这个问题标记为"已回答".


这取决于您希望通过共享控制器来实现的目标; 您可以共享同一个控制器(虽然具有不同的实例),也可以共享同一个控制器实例.

共享一个控制器

两个指令可以通过将相同的方法传递给两个指令来使用相同的控制器,如下所示:

app.controller( 'MyCtrl', function ( $scope ) {
  // do stuff...
});

app.directive( 'directiveOne', function () {
  return {
    controller: 'MyCtrl'
  };
});

app.directive( 'directiveTwo', function () {
  return {
    controller: 'MyCtrl'
  };
});
Run Code Online (Sandbox Code Playgroud)

每个指令都将获得自己的控制器实例,但这允许您在任意数量的组件之间共享逻辑.

需要一个控制器

如果要共享控制器的同一实例,则使用require.

require确保存在另一个指令,然后将其控制器作为链接功能的参数.因此,如果您在一个元素上有两个指令,那么您的指令可能需要存在另一个指令并获得对其控制器方法的访问权限.一个常见的用例是要求ngModel.

^require,添加了插入符号,除了当前元素之外还检查上述指令元素,以尝试查找其他指令.这允许您创建复杂的组件,其中"子组件"可以通过其控制器与父组件通信,从而产生很好的效果.示例可以包括标签,其中每个窗格可以与整个标签通信以处理切换; 手风琴套装可以确保一次只开一个; 等等

在任何一种情况下,您必须一起使用这两个指令才能使用.require是一种在组件之间进行通信的方式.

有关详细信息,请查看指令的指南页面:http://docs.angularjs.org/guide/directive

  • 是否可以要求兄弟指令控制器?基本上我需要在兄弟指令之间共享控制器或服务的相同实例(在DOM兄弟中,而不是在相同的DOM元素上),使用ng-repeat重复.想象一下,每个重复的项目都有一个指令,需要它们之间的共享状态或逻辑. (3认同)
  • @CMCDragonkai没有办法做到这一点,但有两种常见的方法来完成同样的事情.第一个是如果兄弟姐妹都是相同的"类型",那么ngRepeat上面的元素可以像容器指令一样,然后所有子元素都需要该指令,所有子元素都共享同一个控制器.更常见的解决方案 - 通常更规范 - 是使用共享服务.你能详细说明这些兄弟姐妹做了什么以及他们需要分享什么吗? (2认同)

Jos*_*ter 27

Mark Rajcok在这里有一个很好的stackoverflow答案:

AngularJS指令控制器需要父指令控制器?

链接到这个非常明确的jsFiddle:http://jsfiddle.net/mrajcok/StXFK/

<div ng-controller="MyCtrl">
    <div screen>
        <div component>
            <div widget>
                <button ng-click="widgetIt()">Woo Hoo</button>
            </div>
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的

var myApp = angular.module('myApp',[])

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        require: '^screen',
        controller: function($scope) {
            this.componentFunction = function() {
                $scope.screenCtrl.doSomethingScreeny();
            }
        },
        link: function(scope, element, attrs, screenCtrl) {
            scope.screenCtrl = screenCtrl
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})


//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
    $scope.name = 'Superhero';
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,让Mark Markcok的榜样点击最多的是关注控制器方法是如何创建的.通常,您会看到通过$ scope.methodName = function(){...}创建的控制器方法,但为了使其起作用,您必须将this.methodName用于您想要访问的方法.起初我没有注意到. (4认同)