ディレクティブ定義のトランスクルードオプションを理解していますか?


195

これは、angularjsのディレクティブで理解するのが最も難しい概念の1つだと思います。

http://docs.angularjs.org/guide/directiveからのドキュメントは言う:

transclude-要素のコンテンツをコンパイルして、ディレクティブで利用できるようにします。通常、ngTranscludeと共に使用されます。トランスクルージョンの利点は、リンク機能が正しいスコープに事前バインドされたトランスクルージョン機能を受け取ることです。通常の設定では、ウィジェットは分離スコープを作成しますが、トランスクルージョンは子ではなく分離スコープの兄弟です。これにより、ウィジェットがプライベート状態を持ち、トランスクルージョンが親(事前分離)スコープにバインドされるようになります。

  • true-ディレクティブのコンテンツをトランスクルードします。
  • 'element'-低い優先度で定義されたディレクティブを含む要素全体をトランスクルードします。

それは言うtransclude一般的に使用しましたngTransclude。ただし、ngTranscludeのドキュメントのサンプルでは、ngTranscludeディレクティブをまったく使用していません。

これを理解するのに役立つ良い例をいくつか教えてください。なぜそれが必要なのですか?それは何を解決しますか?どうやって使うのですか?


FYI ...リンクは少なくとも今は機能しています
Sandy

回答:


518

要素にmyDirectiveというディレクティブがあり、その要素が他のコンテンツを囲んでいるとします。

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>

myDirectiveがテンプレートを使用している場合は、のコンテンツが<div my-directive>ディレクティブテンプレートに置き換えられることがわかります。だから:

app.directive('myDirective', function(){
    return{
        template: '<div class="something"> This is my directive content</div>'
    }
});

このレンダリングになります:

<div class="something"> This is my directive content</div> 

元の要素のコンテンツは<div my-directive> 失われます(より正確には、置き換えられます)。だから、これらの仲間に別れを告げる:

<button>some button</button>
<a href="#">and a link</a>

だから、あなたはあなたの保つために何をしたい場合<button>...<a href>...DOMに?トランスクルージョンと呼ばれるものが必要です。概念は非常に単純です。ある場所から別の場所にコンテンツを含めます。したがって、ディレクティブは次のようになります。

app.directive('myDirective', function(){
    return{
        transclude: true,
        template: '<div class="something"> This is my directive content</div> <ng-transclude></ng-transclude>'
    }
});

これはレンダリングします:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>. 

結論として、ディレクティブを使用しているときに要素のコンテンツを保持したい場合は、基本的にトランスクルードを使用します。

私のコード例はこちらです。あなたもこれを見ることから利益を得ることができます。


12
機能が少し変わったようです。バージョンが少なくとも1.2.9以上。テンプレートのコンテンツは、レンダリングされたコンテンツに追加されません。以下の@TechExplorerの回答を参照してください
Tarjei Romtveit 14年

20
非常に良い答えです。通常よりはるかに上です。あなたは良い例を持っています、そしてあなたの「これは私の指示内容です」はレンダリングされたバージョンで非常に読みやすくしました。なぜAngularが複雑な用語や概念を使用しなければならないのか理解できず、あなたのような理解しやすい例が含まれていません。+2
freeall

変換されたコンテンツがディレクティブの分離スコープフィールドを参照できるかどうか誰かが知っていますか?トランスクルージョンは分離スコープの子ではなく兄弟であることを上に述べています...だから私はそれができないと思います-しかし、誰かが可能かどうか確認したり、私に知らせたりできるかどうか疑問に思っていました
Simon Green

@UladzimirHavenchykありがとう、ビデオを別の場所に移動しました。それに応じてリンクを修正しました。
odiseo

4
@ odiseo、Angularのドキュメントはすべて、このようにわかりやすい英語でわかりやすく記述してください。+ 1が多い。
Dan Hodson 2016年

76

AngularJSの新しいバージョンでの上記の動作の変更について言及することが重要だと思います。Angular 1.2.10で上記の結果を達成するために1時間を費やしました。

ng-transcludeを含む要素のコンテンツは追加されませんが、完全に置き換えられます。

したがって、上記の例では、 'transclude'で達成できることは次のようになります。

<div class="something">
    <button>some button</button>
    <a href="#">and a link</a>
</div>

ではなく

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>

ありがとう。


Angular 1.2で変更された動作の詳細については、change eed299aを参照してください。
Mark Rajcok、2015

37

TechExplorerの発言は本当ですが、テンプレートにng-transclude属性を持つ単純なコンテナータグ(divやspanなど)を含めることで、両方のコンテンツを持つことができます。これは、テンプレートの次のコードにすべてのコンテンツを含める必要があることを意味します

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>

5
それが他の回答に欠けていた重要な情報でした
Matheus

4
この答えは非常に多くの情報を追加します。ng-transcludeプレースホルダーとして機能する属性であり、その中にトランスクルードされたコンテンツが配置されます。
BeingSuman 2016年

5

Wikiから:

「コンピューターサイエンスでは、トランスクルージョンとは、電子ドキュメントの一部またはすべてを、参照により1つ以上の他のドキュメントに含めることです。」

トランスクルージョンの別の使用法を追加したいと思います。これは、親ディレクティブと子ディレクティブのコンパイルおよびリンク関数の実行順序を変更することです。親DOMはおそらく子DOMに依存しているため、これは親DOMの前に子DOMをコンパイルする場合に役立ちます。この記事は、より深く掘り下げて非常に明確にしています!

http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives-part-2-transclusion/


5

更新AngularJS 1.6.6ドキュメントには、今より良い説明があります。

Transcludeは、他の要素をラップするディレクティブを作成するために使用されます

文字列やオブジェクトではなく、テンプレート全体を渡すことが望ましい場合があります。「ダイアログボックス」コンポーネントを作成するとします。ダイアログボックスは、任意のコンテンツをラップできる必要があります。

これを行うには、transcludeオプションを使用する必要があります。以下の例を参照してください。


script.js

angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
  $scope.name = 'Tobias';
}])
.directive('myDialog', function() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    templateUrl: 'my-dialog.html',
    link: function(scope) {
      scope.name = 'Jeff';
    }
  };
});

index.html

<div ng-controller="Controller">
  <my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>

my-dialog.html

<div class="alert" ng-transclude></div>

コンパイルされた出力

<div ng-controller="Controller" class="ng-scope">
  <my-dialog class="ng-isolate-scope"><div class="alert" ng-transclude="">Check out the contents, Tobias!</div></my-dialog>
</div>

Transcludeは、このオプションを使用してディレクティブの内容を、ディレクティブの内部ではなく外部にアクセスできるようにします。

これは前の例で説明されています。名前をJeffとして再定義するリンク関数をscript.jsに追加したことに注意してください。通常、{{name}}がジェフになることを期待します。ただし、この例では、{{name}}バインディングがまだTobiasであることがわかります。

ベストプラクティスtransclude: true任意のコンテンツをラップするディレクティブを作成する場合にのみ使用します。


0

transclude:trueは、ディレクティブのテンプレート要素を使用して、ディレクティブで定義されているすべての要素を追加することを意味します。

transclude:falseの場合、これらの要素はディレクティブの最終的なhtmlに含まれず、ディレクティブのテンプレートのみがレンダリングされます。

transclude:elementは、ディレクティブテンプレートが使用されないことを意味します。ディレクティブで定義された要素のみがHTMLとしてレンダリングされます。

ディレクティブを定義するときはEに制限する必要があり、ページに追加するとき

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.