将 $properties 添加到 Transcluded 范围
Adding $properties to Transcluded Scope
我有一个带有嵌入范围的指令,如下所示:
<my-control>
Some Content: {{value}}
</my-control>
其中 value
来自父范围。
我想添加一个与控件作用域交互的函数,所以我可以这样做:
<my-control>
Some Content: {{value}}
<button ng-click="$close()">Close</button>
</my-control>
类似于 ngRepeat
将 $index
等属性添加到行范围的方式。在我的指令中执行此操作的最简单方法是什么?
您可以在您的指令链接函数中将新方法附加到您的范围(如果您有的话,甚至可以在指令的控制器中)。
为了简单起见,我将在这里展示如何将新方法附加到指令的链接函数:
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
希望这对您有所帮助,如果我遗漏了什么,请随时告诉我,我很乐意提供任何其他信息。
当我们不指定 scope:true
(new Scope) 或 scope:{}
(isolatedScope) 并且当我们重新使用该指令时,在范围上定义的属性将被覆盖。
例如:
<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()
扩展指令的范围。并更新其中的属性。
解决方案 1 可能并非在所有情况下都有效。当我们访问 firstChild
时,如果它还没有准备好 Solution1 将失败 .
解决方案 2 更简洁,适用于所有情况。
Vinay 的回答是正确的,但我会对其进行一些改动以使其更加 "Angular"
公开指令 API 的 "angular" 方法是通过控制器。我会遵循 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>
我有一个带有嵌入范围的指令,如下所示:
<my-control>
Some Content: {{value}}
</my-control>
其中 value
来自父范围。
我想添加一个与控件作用域交互的函数,所以我可以这样做:
<my-control>
Some Content: {{value}}
<button ng-click="$close()">Close</button>
</my-control>
类似于 ngRepeat
将 $index
等属性添加到行范围的方式。在我的指令中执行此操作的最简单方法是什么?
您可以在您的指令链接函数中将新方法附加到您的范围(如果您有的话,甚至可以在指令的控制器中)。
为了简单起见,我将在这里展示如何将新方法附加到指令的链接函数:
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
希望这对您有所帮助,如果我遗漏了什么,请随时告诉我,我很乐意提供任何其他信息。
当我们不指定 scope:true
(new Scope) 或 scope:{}
(isolatedScope) 并且当我们重新使用该指令时,在范围上定义的属性将被覆盖。
例如:
<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()
扩展指令的范围。并更新其中的属性。
解决方案 1 可能并非在所有情况下都有效。当我们访问 firstChild
时,如果它还没有准备好 Solution1 将失败 .
解决方案 2 更简洁,适用于所有情况。
Vinay 的回答是正确的,但我会对其进行一些改动以使其更加 "Angular"
公开指令 API 的 "angular" 方法是通过控制器。我会遵循 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>