Angularjs 将$properties添加到转移范围
我有一个指令,它的作用域是这样的:Angularjs 将$properties添加到转移范围,angularjs,transclusion,Angularjs,Transclusion,我有一个指令,它的作用域是这样的: <my-control> Some Content: {{value}} </my-control> <my-control> Some Content: {{value}} <button ng-click="$close()">Close</button> </my-control> app.directive('myControl', function()
<my-control>
Some Content: {{value}}
</my-control>
<my-control>
Some Content: {{value}}
<button ng-click="$close()">Close</button>
</my-control>
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);
});
}
}
});
类似于
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...");
};
}
};
});
<my-control>
Click <a href ng-click="$close();">close</a> things.
</mycontrol>
app.directive('myControl',function(){
返回{
限制:'E',
是的,
模板:“”,
链接:功能后链接(范围){
作用域$close=函数close(){
log(“关闭指令中的函数…”);
};
}
};
});
在HTML中,您应该能够简单地调用该函数:
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...");
};
}
};
});
<my-control>
Click <a href ng-click="$close();">close</a> things.
</mycontrol>
点击物品。
还可以使用上面的示例来检查此plunker的实际操作:
我希望这有帮助,如果我遗漏了什么,请随时告诉我,我将很高兴包含任何其他信息。当我们不指定
范围:true
(新范围)或范围:{}
(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>
在这里,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);
});
}
}
});
app.directive('myControl',function(){
返回{
限制:'E',
是的,
模板:“欢迎使用testMe指令!”,
链接:函数(作用域、元素、属性、directiveCtrl、transcludeFn){
var transclusionScope=scope.$new(),
transclusionTarget=元素[0]。查询选择器(“[transclude target]”);
transclusionScope.name=attrs.name;
transcludeFn(transclusionScope,函数(clone){
元素(transclusionTarget).append(克隆);
});
}
}
});
在这里,使用Scope.$new()
创建一个新范围
扩展指令的范围。并更新其中的属性
解决方案1可能不适用于所有情况。当我们访问firstChild
时,如果未准备好解决方案1将失败
解决方案2更干净,在所有情况下都有效 Vinay的答案是正确的,但我想给它添加一个转折点,使它更“棱角分明” 公开指令API的“角度”方式是通过控制器。我将遵循ngForm指令使用的模式- 大概是这样的:
<my-control>
Some Content: {{value}}
</my-control>
<my-control>
Some Content: {{value}}
<button ng-click="$close()">Close</button>
</my-control>
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);
});
}
}
});
app.directive('myControl',function(){
返回{
限制:'E',
是的,
控制器:功能($scope){
这是。$close=function(){
//关上我
}
这是。$open=function(){
//打开我
}
}
模板:“欢迎使用testMe指令!”,
链接:函数(作用域、元素、属性、directiveCtrl、transcludeFn){
transcludeFn(作用域$new(),函数(克隆,transclusionScope){
//仅当name属性存在时,才向作用域公开API
如果(属性名称){
transclusionScope[name]=directiveCtrl;
}
元素(元素[0]。查询选择器(“[transclude target]”)。追加(克隆);
});
}
}
});
使用时:
<my-control name="myControl2">
<button ng-click="myControl2.$close()>Close</button>
</my-control>
嘿,保罗!这对你有用吗?@sergiocruz,我需要指令有一个独立的作用域,请参阅接受的答案。是的……我只想指出,如果你在指令声明中添加scope:{}
,最终结果是一样的。再加上一点更干净的IMHO:)如果你添加自己的方法,为了与AngularJS惯例保持一致,你应该避免使用“$”前缀。嘿,Steve,尽管我同意,我只是想与Paul的问题保持一致,这样我就不会把他弄糊涂了(他问的是$close方法)。此外,值得一提的是,像angular ui这样的大型库确实会在其服务的前面加上$。只是将其放在那里。这之所以有效,是因为指令没有声明自己的作用域,而是将方法附加到继承的作用域,而继承的作用域将可供指令和转置的内容访问。问题是,这也意味着$close方法在指令范围之外是可访问的。在同一父作用域中包含其中两个指令,$close方法将被覆盖。非常感谢,解决方案2成功了。实际上,我也尝试过类似的方法,但当我只想修改作用域,并且我很确定我做错了时,对DOM的处理似乎有点复杂。我想这确实是正确且唯一的选择。我认为在我的例子中,使用控件的名称将大大增加与父作用域发生冲突的几率。另外,ngRepeat将$index等属性直接添加到作用域中,因此这里有一个“官方”API的例子,它的工作方式正好相反。使用“name”属性的意义在于,它可以让您控制如何将API添加到作用域中-因此,如果发生冲突,您只需更改名称即可。在这种情况下,碰撞的可能性为0%。我也不认为将方法(或属性)直接添加到子范围是“错误的”。我刚刚通过经验发现,我所建议的方法效果很好,特别是如果指令的API有多个方法或属性的话。