自分が正しいことをしているか知りたい。
プリアンブル: リソースを消費し、結果をそれ自体に格納する Typeahead クラスを開発しました。クラスには、多かれ少なかれ次の構造があります。
- 入力:検索テキストが格納される場所。
- リスト:結果が格納される場所。
- change:入力が変化するたびに実行される関数。
- カーソル:現在ホバー/選択されている要素を追跡する関数。
問題は、必要なすべてのプロパティを入力にアタッチしたい場合、コードが肥大化して見えることです。
<input
type="text"
ng-model="myTa.input"
ng-change="myTa.change();"
ng-keyup="myTa.cursor()"
....
/>
私が達成したかったのは、Typeahead インスタンスのみを必要とし、必要なすべてのプロパティを要素に自動的にアタッチするディレクティブでした。例えば:
<input type="text" my-typeahead="myTa" />
続行する前に、次のことを明確にしたいと思います。
- ディレクティブを非常に柔軟にして、入力、テキストエリア、選択、さらにはリンクにアタッチできるようにしたいので、テンプレートも templateUrl も使用したくありません。
- 私は attrs.$observe または scope.$watch を使用したくありません。なぜなら、ng-model は優れた仕事をし、私が探しているものを達成するからです。
- ルート要素内の新しい要素はトリックなしでコンパイルされますが、親自体は新しいディレクティブをコンパイルしません。(これは理にかなっています)
さて、これをやったら地獄に落ちますか?
angular
.module('myTypeaheadDirective', [])
.directive('myTypeahead', function($compile, $rootScope) {
return {
restrict: 'A',
scope: {
typeahead: '=myTypeahead'
},
compile: function() {
return {
pre: function precompile(scope, element, attrs) {
var installedAttribute = 'my-typeahead-installed';
if ( angular.isUndefined( element.attr( installedAttribute ) ) ) {
element.attr('ng-model', 'typeahead.input');
element.attr('ng-change', 'typeahead.change()');
element.attr( installedAttribute, true );
$compile(element)(scope.$parent);
}
}
}
}
}
});
コードを説明するには:
ディレクティブの事前コンパイル プロセスは、それが既にインストールされているかどうかをチェックします。インストールされていない場合、無限ループに陥ります。
条件内に、必要な数のディレクティブを追加します。
ng-model="typeahead.input" を使用していることに注意してください。ただし、これは分離されたスコープであるため、異なる typeahead インスタンスを持つ複数の入力を持つことができます。
新しいディレクティブをアタッチした後、$compile サービスを使用して、親スコープを使用して要素を再コンパイルします (元の typeahead インスタンスにアクセスできるようにします)。
私の質問は次のとおりです。
- 私がここでやっていることは素朴ですか?
- これを行うより良い方法はありますか?
- 要素を再コンパイルすると、パフォーマンスの問題が発生しますか?
- このような方法で親スコープにアクセスすると問題が発生しますか?
お時間を割いていただきありがとうございます:)