web-dev-qa-db-fra.com

ID uniques du modèle de directive pour les éléments dans AngularJS

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>
66
NoRyb

HTML

    <div class="myDirective">
        <input type="checkbox" id="myItem_{{$id}}" />
        <label for="myItem_{{$id}}">open myItem_{{$id}}</label>
    </div>
88
BuriB

MISE À JOUR

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++;
        }
    }
})

Ne liez qu'une fois:

  • Si vous devez uniquement lier une valeur une fois, vous ne devez pas utiliser de liaisons ({{}}/ng-bind).
  • les fixations sont chères car elles utilisent $ watch. Dans votre exemple, à chaque $ digest, angular) vérifie si vos identifiants sont modifiés, mais vous ne les définissez qu'une fois.
  • Vérifiez ce module: 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);
        }
    }
})
52
Ilan Frumer

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>
2
Raf

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é:

https://stackoverflow.com/a/14729165/1288552

1
NoRyb