2

<select>要素で使用できるディレクティブを作成して、<select>動的に更新され、アプリ内のすべてのコンポーネント間で共有される、グローバルに知られているリストを設定するように指示したいと考えています。

私はそれを次のように使用することを想定しています:

<select ng-model="listentry" select-the-list></select>

これが私がこれまでに行っている方法です:

.directive('selectTheList', function ($compile, ListData) {
    return {
        restrict: 'A',
        priority: 1000,
        terminal: true,
        link: function (scope, el, attributes) {
            var child = scope.$new();
            child.listData = ListData.theList;
            el.attr('ng-options', 'listItem.name for listItem in listData track by listItem.id');
            el.removeAttr('select-the-list'); /**** ATTENTION ****/
            $compile(el)(child);
        }
    };
});

つまり、ng-optionsこの目的のために設定したスコープに基づいて、必要な機能を実行する属性を割り当ててから、それを割り当てます$compile


これはうまくいきます。しかし、私がATTENTIONでコメントした行に注意してください: これは、ユーザーが<select select-the-list>を使用したことを前提としていますselectTheList。ただし、ディレクティブ docsによると:

Angularは要素のタグと属性名を正規化し、どの要素がどのディレクティブに一致するかを判断します。通常、大文字と小文字を区別するキャメルケースの 正規化された名前 (例: ngModel) でディレクティブを参照します。ただし、HTML では大文字と小文字が区別されないため、DOM 内のディレクティブを小文字の形式で参照します。通常は、DOM 要素のダッシュ区切りのng-model属性を使用します (例: )。

正規化のプロセスは次のとおりです。 [... 中略 ...]

たとえば、次の形式はすべて同等であり、ngBindディレクティブに一致します。

<div ng-controller="Controller">
  Hello <input ng-model='name'> <hr/>
  <span ng-bind="name"></span> <br/>
  <span ng:bind="name"></span> <br/>
  <span ng_bind="name"></span> <br/>
  <span data-ng-bind="name"></span> <br/>
  <span x-ng-bind="name"></span> <br/>
</div>

つまり、ユーザーが実行<select select:the:list>すると、ディレクティブが適用され、機能element.removeAttr('select-the-list')せず、無限ループが発生します


これはXY 問題である可能性があるため、このコンテキストをすべて提供しました。しかし、これが良い方法である場合、ディレクティブが呼び出される原因となった要素の実際の属性を見つける最良の方法は何ですか?再コンパイルする前に削除できますか?

4

2 に答える 2

1

これは確かに XY 問題です。対象が再帰的なコンパイルを回避しているためです。

これを処理するにはいくつかのトリックがあります。

それらの 1 つは、DDO オブジェクトがそのまま利用できる唯一の場所であるという事実を利用することthisですcompile

...
compile: function (element, attrs)  {
  attrs.$set(this.name, null);
  // so the appearance of 'compile' won't require nesting link fn
  return this.link;
},
link: ...

また、ディレクティブの名前を変更したり、そのコードを貼り付けたりしても、矛盾は発生しません。

別のものはより一般的であり、何らかの理由で属性の削除が適用できない場合、またはディレクティブが属性ではない場合に特に役立ちます。

link: function (scope, element) {
    ...
    if (element.data('$recursion')) {
        element.data('$recursion', false);
    } else {
        element.data('$recursion', true);
        $compile(element)(scope);
    }
}
于 2015-11-12T00:54:43.640 に答える