I have a directive that can be used multiple times on a page. In the template of this directive, I need to use IDs for an input-Element so I can "bind" a Label to it like so:
我有一个可以在页面上多次使用的指令。在这个指令的模板中,我需要使用id作为输入元素,这样我就可以像这样“绑定”标签到它:
<input type="checkbox" id="item1" /><label for="item1">open</label>
Now the problem is, as soon as my directive is included multiple times, the ID "item1" is not unique anymore and the label doesn't work correctly (it should check/uncheck the checkbox when clicked).
现在的问题是,只要我的指令被包含多次,ID“item1”就不再是唯一的,标签也不能正常工作(点击时应该选中/取消复选框)。
How is this problem fixed? Is there a way to assign a "namespace" or "prefix" for the template (like asp.net does with the ctl00...-Prefix)? Or do I have to include an angular-Expression in each id-Attribute which consists of the directive-ID from the Scope + a static ID. Something like:
这个问题怎么解决?是否有方法为模板分配一个“名称空间”或“前缀”(如asp.net使用ctl00…-前缀)?或者,我必须在每个ID属性中包含一个angular表达式,它包含来自Scope的direcid ID +一个静态ID。
<input type="checkbox" id="{{directiveID}} + 'item1'" /><label for="{{directiveID}} + 'item1'">open</label>
Edit:
编辑:
My Directive
我的指令
module.directive('myDirective', function () {
return {
restrict: 'E',
scope: true,
templateUrl: 'partials/_myDirective.html',
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
...
} //controller
};
}]);
My HTML
我的HTML
<div class="myDirective">
<input type="checkbox" id="item1" /><label for="item1">open</label>
</div>
4 个解决方案
#1
85
HTML
HTML
<div class="myDirective">
<input type="checkbox" id="myItem_{{$id}}" />
<label for="myItem_{{$id}}">open myItem_{{$id}}</label>
</div>
#2
51
UPDATE
Angular 1.3 introduced a native lazy one-time binding. from the angular expression documentation:
角1.3引入了一个本地延迟的一次性绑定。从角度表达文档来看:
One-time binding
一次性绑定
An expression that starts with :: is considered a one-time expression. One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value (see value stabilization algorithm below).
以:开头的表达式被认为是一次性表达式。一旦表达式稳定后,一次性表达式将停止重新计算,如果表达式结果为非定义值,则在第一次摘要之后发生(参见下面的值稳定算法)。
Native Solution:
本地解决方案:
.directive('myDirective', function() {
var uniqueId = 1;
return {
restrict: 'E',
scope: true,
template: '<input type="checkbox" id="{{::uniqueId}}"/>' +
'<label for="{{::uniqueId}}">open</label>',
link: function(scope, elem, attrs) {
scope.uniqueId = 'item' + uniqueId++;
}
}
})
Only bind once:
- If you only need to bind a value once you should not use bindings ({{}} / ng-bind)
- 如果您只需要绑定一个值,那么不应该使用bindings ({{} / ng-bind)
- bindings are expensive because they use $watch. In your example, upon every $digest, angular dirty checks your IDs for changes but you only set them once.
- 绑定很贵,因为它们使用$watch。在您的示例中,在每一次$digest中,角脏检查您的id是否有更改,但您只设置一次。
- Check this module: https://github.com/Pasvaz/bindonce
- 检查这个模块:https://github.com/Pasvaz/bindonce
Solution:
解决方案:
.directive('myDirective', function() {
var uniqueId = 1;
return {
restrict: 'E',
scope: true,
template: '<input type="checkbox"/><label>open</label>',
link: function(scope, elem, attrs) {
var item = 'item' + uniqueId++;
elem.find('input').attr('id' , item);
elem.find('label').attr('for', item);
}
}
})
#3
2
We add a BlockId parameter to the scope, because we use the id in our Selenium tests for example. There is still a chance of them not being unique, but we prefer to have complete control over them. Another advantage is that we can give the item a more descriptive id.
我们向范围添加了一个BlockId参数,因为我们在Selenium测试中使用id。它们仍然有可能不是唯一的,但我们更喜欢完全控制它们。另一个优点是我们可以给项目一个更描述性的id。
Directive JS
指令JS
module.directive('myDirective', function () {
return {
restrict: 'E',
scope: {
blockId: '@'
},
templateUrl: 'partials/_myDirective.html',
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
...
} //controller
};
}]);
Directive HTML
指令的HTML
<div class="myDirective">
<input type="checkbox" id="{{::blockId}}_item1" /><label for="{{::blockId}}_item1">open</label>
</div>
Usage
使用
<my-directive block-id="descriptiveName"></my-directive>
#4
1
Apart from Ilan and BuriB's solutions (which are more generic, which is good) I found a solution to my specific problem because I needed IDs for the "for" Attribute of the label. Instead the following code can be used:
除了Ilan和BuriB的解决方案(更通用,这很好)之外,我找到了一个解决我具体问题的解决方案,因为我需要id作为标签的“for”属性。相反,可以使用以下代码:
<label><input type="checkbox"/>open</label>
The following *-Post has helped:
下面的*-Post帮助了我们:
https://*.com/a/14729165/1288552
https://*.com/a/14729165/1288552
#1
85
HTML
HTML
<div class="myDirective">
<input type="checkbox" id="myItem_{{$id}}" />
<label for="myItem_{{$id}}">open myItem_{{$id}}</label>
</div>
#2
51
UPDATE
Angular 1.3 introduced a native lazy one-time binding. from the angular expression documentation:
角1.3引入了一个本地延迟的一次性绑定。从角度表达文档来看:
One-time binding
一次性绑定
An expression that starts with :: is considered a one-time expression. One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value (see value stabilization algorithm below).
以:开头的表达式被认为是一次性表达式。一旦表达式稳定后,一次性表达式将停止重新计算,如果表达式结果为非定义值,则在第一次摘要之后发生(参见下面的值稳定算法)。
Native Solution:
本地解决方案:
.directive('myDirective', function() {
var uniqueId = 1;
return {
restrict: 'E',
scope: true,
template: '<input type="checkbox" id="{{::uniqueId}}"/>' +
'<label for="{{::uniqueId}}">open</label>',
link: function(scope, elem, attrs) {
scope.uniqueId = 'item' + uniqueId++;
}
}
})
Only bind once:
- If you only need to bind a value once you should not use bindings ({{}} / ng-bind)
- 如果您只需要绑定一个值,那么不应该使用bindings ({{} / ng-bind)
- bindings are expensive because they use $watch. In your example, upon every $digest, angular dirty checks your IDs for changes but you only set them once.
- 绑定很贵,因为它们使用$watch。在您的示例中,在每一次$digest中,角脏检查您的id是否有更改,但您只设置一次。
- Check this module: https://github.com/Pasvaz/bindonce
- 检查这个模块:https://github.com/Pasvaz/bindonce
Solution:
解决方案:
.directive('myDirective', function() {
var uniqueId = 1;
return {
restrict: 'E',
scope: true,
template: '<input type="checkbox"/><label>open</label>',
link: function(scope, elem, attrs) {
var item = 'item' + uniqueId++;
elem.find('input').attr('id' , item);
elem.find('label').attr('for', item);
}
}
})
#3
2
We add a BlockId parameter to the scope, because we use the id in our Selenium tests for example. There is still a chance of them not being unique, but we prefer to have complete control over them. Another advantage is that we can give the item a more descriptive id.
我们向范围添加了一个BlockId参数,因为我们在Selenium测试中使用id。它们仍然有可能不是唯一的,但我们更喜欢完全控制它们。另一个优点是我们可以给项目一个更描述性的id。
Directive JS
指令JS
module.directive('myDirective', function () {
return {
restrict: 'E',
scope: {
blockId: '@'
},
templateUrl: 'partials/_myDirective.html',
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
...
} //controller
};
}]);
Directive HTML
指令的HTML
<div class="myDirective">
<input type="checkbox" id="{{::blockId}}_item1" /><label for="{{::blockId}}_item1">open</label>
</div>
Usage
使用
<my-directive block-id="descriptiveName"></my-directive>
#4
1
Apart from Ilan and BuriB's solutions (which are more generic, which is good) I found a solution to my specific problem because I needed IDs for the "for" Attribute of the label. Instead the following code can be used:
除了Ilan和BuriB的解决方案(更通用,这很好)之外,我找到了一个解决我具体问题的解决方案,因为我需要id作为标签的“for”属性。相反,可以使用以下代码:
<label><input type="checkbox"/>open</label>
The following *-Post has helped:
下面的*-Post帮助了我们:
https://*.com/a/14729165/1288552
https://*.com/a/14729165/1288552