请考虑Plunk。
我正在尝试为复杂的指令访问设置测试用例,但是从父指令调用方法时出错:
父指令
app.directive('topParentDirective', [
'$compile',
function($compile){
return {
restrict: 'E',
transclude: true,
template: '<h3>I\'m the parent directive.</h3><div ng-transclude></div>',
controller: function($scope) {
$scope.ActivateMe = function(callerName) {
alert('Parent activated from caller ' + callerName);
};
}
};
}
]);
儿童指令
app.directive('interactingChildDirective', [
'$compile',
function($compile){
return {
scope: {
name: '@'
},
restrict: 'E',
require: ['^topParentDirective'],
templateUrl: 'interactingChildDirective.html',
link: function($scope, $elem, $attrs, $ctrl) {
var self = {};
console.log($ctrl);
$scope.CallTopParent = function() {
$ctrl.ActivateMe($attrs.name);
};
}
};
}
]);
InteractingChildDirective.html
包含:
My name is {{name}}, <button ng-click="CallTopParent()">Click me</button>!
HTML 的
<body ng-app="ngApp">
<div ng-controller="myController">
<top-parent-directive>
<interacting-child-directive name="Child 1"></interacting-child-directive>
</top-parent-directive>
</div>
</body>
问题
TypeError: $ctrl.ActivateMe is not a function
at n.$scope.CallTopParent
这是因为$ ctrl似乎不正确。
我该如何解决这个问题?这可能有点荒谬了......
答案 0 :(得分:2)
应该是
controller: function($scope) {
this.ActivateMe = function(callerName) {
alert('Parent activated from caller ' + callerName);
};
}
因为$ ctrl需要控制器的this
。
答案 1 :(得分:1)
因为您已将子项嵌套在父控制器中,所以您可以使用
访问它的范围$scope.$parent
在你的情况下:
$scope.$parent.ActivateMe($attrs.name);
答案 2 :(得分:0)
estus的回答与评论相结合,有效。为了完整,我想要的场景的工作样本:
Plunkr sample。
更新了Html
<body ng-app="ngApp">
<div ng-controller="myController">
<top-parent-directive>
<interacting-child-directive name="Child 1">
<meaningless-level-directive header="Sub 1">
<interacting-child-directive name="Child 3"/>
</meaningless-level-directive>
</interacting-child-directive>
<interacting-child-directive name="Child 2">
<meaningless-level-directive header="Sub 2">
<interacting-child-directive name="Child 4"/>
</meaningless-level-directive>
</interacting-child-directive>
</top-parent-directive>
</div>
</body>
meaninglessLevelDirective
顾名思义,这只是为了增加额外的水平:
app.directive('meaninglessLevelDirective', [
'$compile',
function($compile){
return {
scope: {
header: '@'
},
restrict: 'E',
transclude: true,
templateUrl: 'meaninglessLevelDirective.html',
controller: function($scope){
}
};
}
]);
meaninglessLevelDirective.html
<div class="meaninglessLevelStyle">
{{header}}
<div style="padding: 10px" ng-transclude>
</div>
</div>