web-dev-qa-db-ja.com

AngularJSの要素のディレクティブテンプレートの一意のID

ページで複数回使用できるディレクティブがあります。このディレクティブのテンプレートでは、ラベルを「バインド」できるようにinput要素にIDを使用する必要があります。

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

問題は、私のディレクティブが複数回含まれるとすぐに、ID「item1」が一意ではなくなり、ラベルが正しく機能しないことです(クリックするとチェックボックスをオン/オフする必要があります)。

この問題はどのように修正されますか?テンプレートに「名前空間」または「プレフィックス」を割り当てる方法はありますか(asp.netがctl00 ...- Prefixで行うように)?または、スコープからのディレクティブID +静的IDで構成される各id属性にangle-Expressionを含める必要がありますか。何かのようなもの:

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

編集:

私の指令

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

私の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

更新

Angular 1.3では、ネイティブレイジーワンタイムバインディングが導入されました。 角度式ドキュメント から:

ワンタイムバインディング

::で始まる式は、1回限りの式と見なされます。 1回限りの式は、安定すると再計算を停止します。これは、式の結果が未定義の値である場合、最初のダイジェスト後に発生します(以下の値安定化アルゴリズムを参照)。

ネイティブソリューション

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

一度だけバインドする:

  • 値を一度だけバインドする必要がある場合は、バインディングを使用しないでください({{}}/ng-bind)
  • バインディングは$ watchを使用するため高価です。あなたの例では、$ [digest]ごとに、angular dirtyはIDの変更をチェックしますが、一度だけ設定します。
  • このモジュールを確認してください: https://github.com/Pasvaz/bindonce

解決策:

.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

たとえば、Seleniumテストでidを使用するため、BlockIdパラメーターをスコープに追加します。それらが一意ではない可能性はまだありますが、完全に制御することをお勧めします。もう1つの利点は、アイテムによりわかりやすいIDを指定できることです。

ディレクティブJS

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

ディレクティブHTML

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

使用法

<my-directive block-id="descriptiveName"></my-directive>
2
Raf

IlanとBuriBのソリューション(より一般的で優れたソリューション)とは別に、ラベルの「for」属性のIDが必要なため、特定の問題のソリューションを見つけました。代わりに、次のコードを使用できます。

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

次のStackoverflow-Postが役立ちました。

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

1
NoRyb