Unikalne identyfikatory szablonów dyrektywy dla elementów

Mam dyrektywę, która może być używana wiele razy na stronie. W szablonie tej dyrektywy muszę użyć IDs dla elementu wejściowego, aby móc "powiązać" z nim Etykietę w ten sposób:

<input type="checkbox" id="item1" /><label for="item1">open</label>

Teraz problem polega na tym, że gdy tylko moja dyrektywa zostanie dołączona kilka razy, identyfikator "item1" nie jest już unikalny, a etykieta nie działa poprawnie(powinna zaznaczyć / odznaczyć pole wyboru po kliknięciu).

Jak rozwiązać ten problem? Czy istnieje sposób na przypisanie "przestrzeni nazw" lub "prefiksu" dla szablon (jak asp.net robi z ctl00...- Prefiks)? Czy też muszę dodawać wyrażenie kątowe do każdego atrybutu id, który składa się z dyrektywy-ID z zakresu + statyczny ID. Coś w stylu:

<input type="checkbox" id="{{directiveID}} + 'item1'" /><label for="{{directiveID}} + 'item1'">open</label>

Edit:

Moja Dyrektywa

module.directive('myDirective', function () {
    return {
        restrict: 'E',
        scope: true, 
        templateUrl: 'partials/_myDirective.html',
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            ...
        } //controller
    };
}]);

Mój HTML

<div class="myDirective">
  <input type="checkbox" id="item1" /><label for="item1">open</label>
</div>
Author: T J, 2014-01-09

4 answers

HTML

    <div class="myDirective">
        <input type="checkbox" id="myItem_{{$id}}" />
        <label for="myItem_{{$id}}">open myItem_{{$id}}</label>
    </div>
 85
Author: BuriB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-09 15:02:55

UPDATE

Angular 1.3 wprowadził natywne, jednorazowe Wiązanie. z dokumentacji wyrażenia kątowego:

Oprawa Jednorazowa

Wyrażenie zaczynające się na:: jest uważane za wyrażenie jednorazowe. Wyrażenia jednorazowe przestaną przeliczać raz są stabilne, co dzieje się po pierwszym przetrawieniu, jeśli wynikiem wyrażenia jest wartość nieokreślona (patrz stabilizacja wartości algorytm poniżej).

Rozwiązanie Natywne :

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

Wiązać tylko raz:

  • jeśli musisz tylko raz wiązać wartość, nie powinieneś używać wiązań ({{}} / ng-bind)
  • wiązania są drogie, ponieważ używają zegarka$. W twoim przykładzie, przy każdym $digest, angular dirty sprawdza Twoje identyfikatory pod kątem zmian, ale ustawiasz je tylko raz.
  • sprawdź ten moduł: https://github.com/Pasvaz/bindonce

Rozwiązanie:

.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
Author: Ilan Frumer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-22 15:02:10

Dodajemy parametr BlockId do zakresu, ponieważ używamy go np. w naszych testach selenu. Nadal istnieje szansa, że nie będą wyjątkowe, ale wolimy mieć nad nimi pełną kontrolę. Kolejną zaletą jest to, że możemy nadać elementowi bardziej opisowy identyfikator.

Dyrektywa JS

module.directive('myDirective', function () {
    return {
        restrict: 'E',
        scope: {
            blockId: '@'
        }, 
        templateUrl: 'partials/_myDirective.html',
        controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
            ...
        } //controller
    };
}]);

Dyrektywa HTML

<div class="myDirective">
  <input type="checkbox" id="{{::blockId}}_item1" /><label for="{{::blockId}}_item1">open</label>
</div>

Użycie

<my-directive block-id="descriptiveName"></my-directive>
 2
Author: Raf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-06 22:48:01

Oprócz rozwiązań Ilana i Buriba (które są bardziej ogólne, co jest dobre) znalazłem rozwiązanie mojego konkretnego problemu, ponieważ potrzebowałem identyfikatorów dla atrybutu "for" etykiety. Zamiast tego można użyć następującego kodu:

<label><input type="checkbox"/>open</label>

Pomógł następujący post Stackoverflow:

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

 1
Author: NoRyb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:36