任何人都可以告诉我如何在另一个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指令中访问控制器,但事实并非如此。有没有更好的方法呢?
答案 0 :(得分:183)
我很幸运并在对这个问题的评论中回答了这个问题,但为了完整起见,我发布了一个完整的答案,所以我们可以将这个问题标记为“已回答”。
这取决于您希望通过共享控制器来实现的目标;你可以共享同一个控制器(虽然有不同的实例),或者你可以共享同一个控制器实例。
分享控制器
两个指令可以通过将相同的方法传递给两个指令来使用同一个控制器,如下所示:
app.controller( 'MyCtrl', function ( $scope ) {
// do stuff...
});
app.directive( 'directiveOne', function () {
return {
controller: 'MyCtrl'
};
});
app.directive( 'directiveTwo', function () {
return {
controller: 'MyCtrl'
};
});
每个指令都将获得自己的控制器实例,但这允许您在任意数量的组件之间共享逻辑。
需要控制器
如果要共享控制器的相同实例,则使用require
。
require
确保存在另一个指令,然后将其控制器作为链接函数的参数。因此,如果您对一个元素有两个指令,那么您的指令可以要求存在另一个指令并获得对其控制器方法的访问权限。一个常见的用例是要求ngModel
。
^require
,添加了插入符号,除了当前元素之外还检查上述指令元素以尝试查找其他指令。这允许您创建复杂的组件,其中“子组件”可以通过其控制器与父组件通信,从而产生很好的效果。示例可以包括标签,其中每个窗格可以与整个标签通信以处理切换;手风琴套装可以确保一次只开一个;等
在任何一种情况下,您必须同时使用这两个指令才能生效。 require
是组件之间进行通信的一种方式。
查看指令的指南页面以获取更多信息:http://docs.angularjs.org/guide/directive
答案 1 :(得分:27)
Mark Rajcok在这里有一个很好的stackoverflow答案:
AngularJS directive controllers requiring parent directive controllers?
链接到这个非常清晰的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';
}