我有一个带有转换范围的指令,如下所示:
<my-control>
Some Content: {{value}}
</my-control>
value
来自父范围。
我想添加一个与控件范围交互的功能,所以我可以这样做:
<my-control>
Some Content: {{value}}
<button ng-click="$close()">Close</button>
</my-control>
与ngRepeat
向行范围添加$index
等属性的方式类似。在我的指令中最简单的方法是什么?
答案 0 :(得分:2)
您可以在指令链接函数中将新方法附加到作用域中(如果有的话,甚至可以在指令的控制器中附加)。
为了简单起见,我将在这里展示如何将新方法附加到指令的链接功能:
app.directive('myControl', function() {
return {
restrict: 'E',
transclude: true,
template: '<div ng-transclude></div>',
link: function postLink(scope) {
scope.$close = function close() {
console.log("Close function that lives in directive...");
};
}
};
});
在您的HTML中,您应该只需简单地调用该函数:
<my-control>
Click <a href ng-click="$close();">close</a> things.
</mycontrol>
还要感觉一下上面的例子,在实践中检查这个plunker: http://plnkr.co/edit/SPSFGcB49qXmXROmNeHj?p=preview
我希望这会有所帮助,如果我错过任何内容,请随时告诉我,我很乐意提供任何其他信息。
答案 1 :(得分:1)
如果我们不指定scope:true
(新范围)或scope:{}
(isolatedScope),并且当我们重新使用该指令时,将覆盖范围上定义的属性。
对于Ex:
<div ng-controller="AppCtrl">
<my-control name="myControl1">
Some Content: {{value}}
My Control Name: {{name}}
</my-control>
<my-control name="myControl2">
Some Content: {{value}}
My Control Name: {{name}}
</my-control>
</div>
不是在屏幕上同时打印myControl1
和myControl2
,而是打印myControl2
两次。
要解决此问题,请尝试以下任何解决方案。
<强>解决方法1 强>
transclde:true
将创建一个新的范围。设置此范围的属性而不是指令的范围。
app.directive('myControl', function() {
return {
restrict: 'E',
transclude: true,
template: '<div><p><strong>Welcome to the testMe directive!</strong></p> <div ng-transclude></div></div>',
link: function(scope, element, attrs) {
var transclusionTarget = element[0].querySelector('[ng-transclude]').firstChild;
var transclusionScope = angular.element(transclusionTarget).scope();
transclusionScope.name = attrs.name;
}
}
});
此处ng-transclude
div下的元素将使用transclusionScope进行编译,抓取并更新其中的属性。
<强>溶液2 强>
而不是使用ng-transclude
,而是手动转换内容。
app.directive('myControl', function() {
return {
restrict: 'E',
transclude: true,
template: '<div><p><strong>Welcome to the testMe directive!</strong></p> <div transclude-target></div></div>',
link: function(scope, element, attrs, directiveCtrl, transcludeFn ) {
var transclusionScope = scope.$new(),
transclusionTarget = element[0].querySelector('[transclude-target]');
transclusionScope.name = attrs.name;
transcludeFn(transclusionScope, function (clone) {
angular.element(transclusionTarget).append(clone);
});
}
}
});
在此处,使用new Scope
创建扩展指令范围的scope.$new()
。并更新其中的属性。
Solution1 可能无法在所有情况下使用。当我们访问firstChild
并且未准备好时解决方案1将失败。
Solution2 更干净,适用于所有情况。
答案 2 :(得分:0)
Vinay的回答是正确的,但我会添加一个扭曲,使其更“Angular”
公开指令API的“角度”方式是通过控制器。我将遵循ngForm指令使用的模式 -
这样的事情:
app.directive('myControl', function() {
return {
restrict: 'E',
transclude: true,
controller: function($scope) {
this.$close = function(){
//close me
}
this.$open = function() {
//open me
}
}
template: '<div><p><strong>Welcome to the testMe directive!</strong></p> <div transclude-target></div></div>',
link: function(scope, element, attrs, directiveCtrl, transcludeFn ) {
transcludeFn(scope.$new(), function (clone, transclusionScope) {
//only expose the API to the scope if the name attribute is present
if(attrs.name) {
transclusionScope[name] = directiveCtrl;
}
angular.element(element[0].querySelector('[transclude-target]').append(clone);
});
}
}
});
用法:
<my-control name="myControl2">
<button ng-click="myControl2.$close()>Close</button>
</my-control>