AngularJSの繊細さ:ディレクティブテンプレート内で選択する

この記事では、1つの特定の問題の解決策と、$ transcludeの仕組みを示す例を説明します。



タスクは次のとおりです。selectのラッパーであるディレクティブを作成します。 selectとlabelの両方を一度に1つのタグで追加したいとします(そしてそこに塗りつぶしエラーを追加できますが、簡単にするためにこれは行いません)。 一般に、一見するとすべてがシンプルに見えます。



ディレクティブを作成して、フィールドと呼びましょう。 次のように使用します。



<field title="" type="select" ng-model="selectedColor" options="color.id as color.name for color in colors"></field>
      
      





私たちはいくつかの属性を思いつきました:





この例のselectedColor



およびcolors



変数は、ディレクティブを使用したスコープ変数であることに注意してください。 ディレクティブが属性にアクセスできるように、属性を介して具体的に指定しました。



指令コード:



 angular.module('directives').directive('field', function () { return { // -    restrict: 'E', // ,      scope: { ngModel: "=", title: "@", type: "@", options: "@" }, //   templateUrl: '/tpl/fields/select.html', });
      
      







テンプレートコード:

 <div class="field"> <label>{{title}}</label> <select ng-model="ngModel" ng-options="{{options}}"></select> </div>
      
      







ライブ: codepen.io/Dzorogh/pen/umCKG?editors=101




すべてがシンプルに見え、動作するはずです。 実行し、デバッガーでチェックインします-

 <field title="" type="select" ng-model="selectedColor" options="color.id as color.name for color in colors"> <label></label> <select ng:options="color.id as color.name for color in colors" ng:model="ngModel"></select> </field>
      
      





悪くないようですが...すべてのオプションはどこにありますか? なぜ色が空(または、未定義)なのですか?



実際、ディレクティブでスコープパラメーターを指定すると、ディレクティブの本体全体が石の壁になり、スコープが分離されます。 この分離されたスコープでは、内部の人々は外部のスコープを見ることができません。 ただし、それに応じて、ディレクティブパラメーターに指定したすべての変数( ngModel, type, title, options



)が分離スコープに追加され、外部変数に「バインド」されます。



そして、ここで問題を見ることができます-それらの変数にcolors



を追加しませんでした。 そして当然のことながら、ディレクティブは、どの種類の配列をそこで使用したいかを知らないはずです。 options属性に書き込むことにより、この配列を使用することを既に示しました。



配列にアクセスするには、少なくとも変数の名前を知っている必要があります。 したがって、最適なオプションはオプションを解析することです。 ここでは、angle.jsのソースコードが役立ちます。ngOptionsには規則性があります。



しかし、外側のスコープから変数名を取得した後でも、内部にどのように追加できますか?



実際には、最も興味深い



ディレクティブの初期化後に外部変数を内部変数にバインドするには、「$ transclude」などを使用する必要があります。 この関数を呼び出すと、外部スコープにアクセスでき、そこから任意の変数を取得し、スコープにディレクティブを「渡す」ことができます。



通常およびトランスクルードを使用した新しいディレクティブ:

 .directive('field', function() { //    angularjs var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/; }; return { restrict: 'E', scope: { ngModel: "=", type: "@", title: "@", options: "@" }, // ""    transclude: true, templateUrl: '/fields/select.html', // $transclude   5 . link: function (scope, element, attrs, controller, $transclude) { if (scope.type == 'select') { //     var parsedOptions = attrs.options.match(NG_OPTIONS_REGEXP); //   (   | ) var optionsArray = /^(.*) \|/.exec(parsedOptions[7]) || parsedOptions[7]; // optionsArray -  ( ) ,     . //     ,      Scope // (,   )    . $transclude(function (clone, $outerScope) { scope[optionsArray] = $outerScope[optionsArray]; }); } } } });
      
      







CodePenの最終オプション: codepen.io/Dzorogh/pen/gBbyI



All Articles