Comprendre l'option transclude de la définition de directive?

195

Je pense que c'est l'un des concepts les plus difficiles à comprendre avec la directive angularjs.

Le document de http://docs.angularjs.org/guide/directive dit:

transclude - compile le contenu de l'élément et le met à la disposition de la directive. Généralement utilisé avec ngTransclude. L'avantage de la transclusion est que la fonction de liaison reçoit une fonction de transclusion qui est pré-liée à la portée correcte. Dans une configuration typique, le widget crée une portée isolée, mais la transclusion n'est pas un enfant, mais un frère de la portée isolée. Cela permet au widget d'avoir un état privé et la transclusion d'être liée à la portée parent (pré-isolée).

  • true - transclut le contenu de la directive.
  • 'élément' - transclut l'élément entier, y compris toutes les directives définies à une priorité inférieure.

Il dit transcludegénéralement utilisé avec ngTransclude. Mais l'exemple du doc ​​de ngTransclude n'utilise pas du tout de ngTranscludedirective.

J'aimerais avoir de bons exemples pour m'aider à comprendre cela. Pourquoi en avons-nous besoin? Que résout-il? Comment l'utiliser?

Freewind
la source
Pour info ... le lien fonctionne au moins maintenant
Sandy

Réponses:

518

Considérons une directive appelée myDirective dans un élément, et cet élément contient un autre contenu, disons:

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

Si myDirective utilise un modèle, vous verrez que le contenu de <div my-directive>sera remplacé par votre modèle de directive. Ayant donc:

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

entraînera ce rendu:

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

Notez que le contenu de votre élément d'origine <div my-directive> sera perdu (ou mieux dit, remplacé). Alors, dites au revoir à ces copains:

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

Alors, que se passe-t-il si vous souhaitez conserver votre <button>...et <a href>...dans le DOM? Vous aurez besoin de quelque chose appelé transclusion. Le concept est assez simple: inclure le contenu d'un endroit à un autre . Alors maintenant, votre directive ressemblera à ceci:

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

Cela rendrait:

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

En conclusion, vous utilisez essentiellement transclude lorsque vous souhaitez conserver le contenu d'un élément lorsque vous utilisez une directive.

Mon exemple de code est ici . Vous pourriez également bénéficier de regarder cela .

odiseo
la source
12
On dirait qu'ils ont un peu changé la fonctionnalité. Au moins dans la version> = 1.2.9. Le contenu du modèle n'est pas ajouté au contenu rendu. Voir la réponse de @ TechExplorer ci
Tarjei Romtveit
20
Une très, très bonne réponse. Bien au-dessus de la normale. Vous avez de bons exemples, et votre "c'est mon contenu directif" le rendait très facile à lire dans la version rendue. Je ne comprends pas pourquoi Angular doit utiliser une terminologie et des concepts complexes, puis ne pas inclure d'exemples faciles à comprendre comme le vôtre. +2
freeall
Quelqu'un sait-il si le contenu transclu peut faire référence aux champs de portée isolée de la directive? Il dit ci-dessus que la transclusion est un frère, pas un enfant, de la portée de l'isolat ... alors je suppose que cela ne peut pas - mais je me demandais si quelqu'un pourrait confirmer ou me faire savoir si c'est possible
Simon Green
@UladzimirHavenchyk merci, ils ont déplacé la vidéo ailleurs. J'ai corrigé le lien en conséquence.
odiseo
4
@odiseo, pourriez-vous s'il vous plaît écrire TOUS les documents angulaires en anglais simple et simple à comprendre comme ça! + plusieurs 1.
Dan Hodson
76

Je pense qu'il est important de mentionner les changements dans le comportement ci-dessus dans la nouvelle version d'AngularJS. J'ai passé une heure à essayer d'obtenir les résultats ci-dessus avec Angular 1.2.10.

Le contenu de l'élément avec ng-transclude n'est pas ajouté mais complètement remplacé.

Donc, dans l'exemple ci-dessus, ce que vous obtiendriez avec «transclude» serait:

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

et pas

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

Merci.

TechExplorer
la source
Pour plus d'informations sur le changement de comportement dans Angular 1.2, voir change eed299a .
Mark Rajcok
37

Ce que TechExplorer dit est vrai, mais vous pouvez avoir les deux contenus en incluant dans votre modèle une simple balise conteneur (comme div ou span) avec l'attribut ng-transclude. Cela signifie que le code suivant dans votre modèle doit inclure tout le contenu

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>
goulpan
la source
5
Ce sont les informations clés qui manquaient dans les autres réponses
Matheus
4
Cette réponse ajoute tellement d'informations. ng-transcludeest l'attribut qui agit comme espace réservé, à l'intérieur duquel le contenu transclus sera placé.
BeingSuman
5

De Wiki:

"En informatique, la transclusion est l'inclusion d'une partie ou de la totalité d'un document électronique dans un ou plusieurs autres documents par référence."

Je voudrais ajouter une autre utilisation pour la transclusion, c'est qu'elle change l'ordre d'exécution des fonctions de compilation et de liaison des directives parent et enfant. Cela peut être utile lorsque vous souhaitez compiler le DOM enfant avant le DOM parent, car le DOM parent dépend peut-être du DOM enfant. Cet article va plus en profondeur et le clarifie très bien!

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

Samir Alajmovic
la source
5

La documentation mise à jour AngularJS 1.6.6 a maintenant une meilleure explication.

Transclude est utilisé pour créer une directive qui enveloppe d'autres éléments

Parfois, il est souhaitable de pouvoir passer un modèle entier plutôt qu'une chaîne ou un objet. Disons que nous voulons créer un composant "boîte de dialogue". La boîte de dialogue doit pouvoir encapsuler tout contenu arbitraire.

Pour ce faire, nous devons utiliser l' option transclude . Reportez-vous à l'exemple ci-dessous.


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>

Sortie compilée

<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 permet au contenu d'une directive avec cette option d'avoir accès à la portée en dehors de la directive plutôt qu'à l'intérieur.

Ceci est illustré dans l'exemple précédent. Notez que nous avons ajouté une fonction de lien dans script.js qui redéfinit le nom en Jeff. Normalement, nous nous attendrions à ce que {{name}} soit Jeff. Cependant, nous voyons dans cet exemple que la liaison {{name}} est toujours Tobias.

Meilleure pratique : utilisez uniquement transclude: truelorsque vous souhaitez créer une directive qui encapsule un contenu arbitraire.

Arthur S
la source
0

transclude: true signifie ajouter tous les éléments définis dans votre directive avec l'élément de modèle de votre directive.

si transclude: false les ces éléments ne sont pas inclus dans votre html final de directive seul le modèle de directive est rendu.

transclude: élément signifie que votre modèle de directive n'est pas utilisé, seuls les éléments définis dans votre directive sont rendus en html.

lorsque vous définissez votre directive, elle doit être limitée à E et lorsque vous l'ajoutez à la page,

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.
dev verma
la source