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

有人能告诉我如何包括控制器从一个指令在另一个 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);
}
};
});

无论如何,我应该能够访问 addProduct 指令中的控制器,但是我没有。还有更好的办法吗?

136248 次浏览

I got lucky and answered this in a comment to the question, but I'm posting a full answer for the sake of completeness and so we can mark this question as "Answered".


It depends on what you want to accomplish by sharing a controller; you can either share the same controller (though have different instances), or you can share the same controller instance.

Share a Controller

Two directives can use the same controller by passing the same method to two directives, like so:

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


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


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

Each directive will get its own instance of the controller, but this allows you to share the logic between as many components as you want.

Require a Controller

If you want to share the same instance of a controller, then you use require.

require ensures the presence of another directive and then includes its controller as a parameter to the link function. So if you have two directives on one element, your directive can require the presence of the other directive and gain access to its controller methods. A common use case for this is to require ngModel.

^require, with the addition of the caret, checks elements above directive in addition to the current element to try to find the other directive. This allows you to create complex components where "sub-components" can communicate with the parent component through its controller to great effect. Examples could include tabs, where each pane can communicate with the overall tabs to handle switching; an accordion set could ensure only one is open at a time; etc.

In either event, you have to use the two directives together for this to work. require is a way of communicating between components.

Check out the Guide page of directives for more info: http://docs.angularjs.org/guide/directive

There is a good stackoverflow answer here by Mark Rajcok:

AngularJS directive controllers requiring parent directive controllers?

with a link to this very clear 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>

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';
}