我正在构建一个AngularJS指令。我希望该指令包含其中包含ng-click的其他内容。单击时,生成的按钮不会执行任何操作。 这是我尝试的代码的简化版本:
(HTML)
<div ng-app="someapp">
<div ng-controller="Ctrl1">
<h2>Example</h2>
<my-dir data-x="1">
<button ng-click="refresh()" id="refresh1">Refresh</button>
</my-dir>
<my-dir data-x="2">
<button ng-click="refresh()" id="refresh2">Refresh</button>
</my-dir>
</div>
</div>
(JavaScript的)
var app = angular.module('someapp', []);
app.controller('Ctrl1', function($scope){ });
app.directive('myDir', function(){
return {
restrict: 'E',
scope: {},
template: '<div><p>Directive contents:</p><div ng-transclude></div></div>',
transclude: true,
link: function(scope, element, attrs){
$scope.y = attrs.x+1;
scope.refresh = function(){
console.log("Refresh Called, y = ", $scope.y);
}
}
};
});
如何更改它以便按钮实际触发$ scope.refresh()函数?
额外澄清:
我需要指令的本地对象信息(单个控制器中可能有多个指令),所以我创建了一个新的范围。
答案 0 :(得分:2)
正如dcodesmith指出的那样,转换的ng-click将绑定到控制器的范围而不是指令的范围。根据您想要做什么,您可能希望这是行为(因为被转换的内容不是指令的一部分,为什么它应该调用指令范围的方法?)。就个人而言,我会在控制器的范围内声明该方法。
app.controller('Ctrl1', function($scope){
$scope.refresh = function() {
console.log("Refresh called.");
};
});
在这种情况下,您的指令应该声明隔离范围,即使其中没有任何内容。
更新:根据您的评论,为什么不在指令模板中包含该按钮?在这种情况下,它已经与正确的范围相关联。
如果在某些情况下你不需要刷新按钮,那么通过指令将其作为选项公开为属性:
<my-dir show-button='true'></my-dir>
// directive scope
scope: {
showButton: '='
}
我使用这种方法遇到的最大问题是使用“双向绑定”运算符(=)将'true'和'false'视为表达式。我只是不喜欢那种感觉。
无论如何,希望这能解决你的问题...... 还有一个评论,我说这甚至不知道你实现的是否实际上是一个刷新按钮,但如果是,我会花一点时间考虑你是否真的需要一个“刷新”按钮。 Angular擅长消除刷新按钮!
更新2:
我创建了一个plunkr,显示我认为我会如何处理你的情况,特别是如果重用任何其他控件:
http://plnkr.co/edit/FhrSwcrSZScvCfhtCSjn
在此示例中,两个按钮指令实际上是“videoPlayer”指令的子代。它们的逻辑包含在该指令中,但它们是单独实例化的,并且父指令不需要操作。 “父指令”(videplayer)简单地公开了要使用的“孩子”的API。也不是父类的方法是构造函数的方法,而不是范围。我认为这很奇怪,但它完全取自角度文档:
http://docs.angularjs.org/guide/directive(页面上的最后一个示例)
请注意,每个videoPlayer指令仍然拥有自己的隔离范围。
答案 1 :(得分:0)
删除scope
对象。那里似乎发生了冲突。
摘自Creating a Directive that Wraps Other Elements
transclude选项会更改范围嵌套的方式。它使得transcluded指令的内容具有指令之外的任何范围,而不是内部的任何范围。这样做,它使内容访问外部范围。
app.directive('myDir', function(){
return {
restrict: 'E',
//scope: {}, remove this line.
template: '<div><p>Directive contents:</p><div ng-transclude></div></div>',
transclude: true,
link: function(scope, element, attrs){
console.log("X-attr", attrs.x);
scope.refresh = function(){
console.log("Refresh Called");
}
}
};
});