web-dev-qa-db-ja.com

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

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

http://docs.angularjs.org/guide/directive のドキュメントには次のように書かれています:

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

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

transcludeは通常、ngTranscludeとともに使用されます。しかし、 ngTransclude のドキュメントのサンプルでは、​​ngTranscludeディレクティブをまったく使用していません。

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

185
Freewind

要素内の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>. 

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

私のコード例は here です。また、 this を見ることも有益です。

494
odiseo

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>

ありがとう。

75
TechExplorer

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

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

ウィキから:

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

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

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

5
Samir Alajmovic

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}}はJeffになると予想されます。ただし、この例では、{{name}}バインディングはまだトバイアスであることがわかります。

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

3
Arthur S

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.
0
dev verma