J'ai une directive qui peut être utilisée plusieurs fois sur une page. Dans le modèle de cette directive, je dois utiliser des identifiants pour un input-Element afin de pouvoir "lier" une étiquette à celle-ci de la manière suivante:
<input type="checkbox" id="item1" /><label for="item1">open</label>
Maintenant, le problème est que, dès que ma directive est incluse plusieurs fois, l'ID "item1" n'est plus unique et l'étiquette ne fonctionne pas correctement (il convient de cocher/décocher la case lorsque vous cliquez dessus).
Comment ce problème est-il résolu? Existe-t-il un moyen d’attribuer un "espace de nom" ou un "préfixe" au modèle (comme le fait asp.net avec le préfixe ctl00 ...)? Ou dois-je inclure une expression angulaire dans chaque attribut id qui consiste en l'ID directive de l'oscilloscope + un identifiant statique? Quelque chose comme:
<input type="checkbox" id="{{directiveID}} + 'item1'" /><label for="{{directiveID}} + 'item1'">open</label>
Edit:
Ma directive
module.directive('myDirective', function () {
return {
restrict: 'E',
scope: true,
templateUrl: 'partials/_myDirective.html',
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
...
} //controller
};
}]);
Mon HTML
<div class="myDirective">
<input type="checkbox" id="item1" /><label for="item1">open</label>
</div>
HTML
<div class="myDirective">
<input type="checkbox" id="myItem_{{$id}}" />
<label for="myItem_{{$id}}">open myItem_{{$id}}</label>
</div>
Angular 1.3 a introduit une liaison ponctuelle paresseuse native. à partir du documentation sur l'expression angulaire :
Liaison unique
Une expression commençant par :: est considérée comme une expression unique. Les expressions uniques arrêtent de recalculer une fois qu'elles sont stables, ce qui se produit après le premier condensé si le résultat de l'expression est une valeur non indéfinie (voir l'algorithme de stabilisation des valeurs ci-dessous).
Solution native :
.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++;
}
}
})
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);
}
}
})
Nous ajoutons un paramètre BlockId à la portée, car nous utilisons l'id dans nos tests Selenium, par exemple. Il y a encore une chance qu'ils ne soient pas uniques, mais nous préférons les contrôler complètement. Un autre avantage est que nous pouvons attribuer à l’article un identifiant plus descriptif.
Directive 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
<div class="myDirective">
<input type="checkbox" id="{{::blockId}}_item1" /><label for="{{::blockId}}_item1">open</label>
</div>
tilisation
<my-directive block-id="descriptiveName"></my-directive>
Outre les solutions d'Ilan et de BuriB (qui sont plus génériques, ce qui est bien), j'ai trouvé une solution à mon problème spécifique car j'avais besoin d'identifiants pour l'attribut "for" de l'étiquette. Au lieu de cela, le code suivant peut être utilisé:
<label><input type="checkbox"/>open</label>
Le Stackoverflow-Post suivant a aidé: