web-dev-qa-db-fra.com

AngularJS: transclude plusieurs sous-éléments en une seule Angular

Je suis assez nouveau pour Angular mais j'ai beaucoup lu. Je lisais sur ng-transclude à http://docs.angularjs.org/guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive et je pense que je comprends bien ce qu'il fait.

Si vous avez une directive qui s'applique à un élément qui contient du contenu, comme dans

<my-directive>directive content</my-directive>

Il vous permettra de marquer un élément dans le modèle de la directive avec ng-transclude et le contenu inclus dans l'élément serait rendu à l'intérieur de l'élément balisé.

donc si le modèle pour myDirective est <div>before</div><div ng-transclude></div><div>after</div> il s'afficherait comme avant le contenu directif.

c'est tout ok. mon Q est-il possible de passer en quelque sorte plus d'un seul bloc de code HTML dans ma directive?

par exemple.

supposons que l'utilisation de la directive ressemble à ceci:

<my-multipart-directive>
     <part1>content1</part1>
     <part2>content2</part2>
</my-multipart-directive>

et avoir un modèle comme:

<div>
  this: <div ng-transclude="part2"></div>
   was after that: <div ng-transclude="part1"></div>
   but now they are switched
<div>

rendre comme

<div>
  this: <div ng-transclude="part2">content2</div>
   was after that: <div ng-transclude="part1">content1</div>
   but now they are switched
<div>

?

(pensant à moi-même) Puis-je en quelque sorte lier la valeur HTML d'un nœud au modèle afin de pouvoir l'utiliser de cette manière sans l'appeler "transclude" ...

Merci

36
epeleg

À partir de Angular 1.5, il est maintenant possible de créer plusieurs emplacements. Au lieu de transclude: true , vous fournissez un objet avec les mappages de chaque slot:

https://docs.angularjs.org/api/ng/directive/ngTransclude

angular.module('multiSlotTranscludeExample', [])
 .directive('pane', function(){
    return {
      restrict: 'E',
      transclude: {
        'title': '?pane-title',
        'body': 'pane-body',
        'footer': '?pane-footer'
      },
      template: '<div style="border: 1px solid black;">' +
                  '<div class="title" ng-transclude="title">Fallback Title</div>' +
                  '<div ng-transclude="body"></div>' +
                  '<div class="footer" ng-transclude="footer">Fallback Footer</div>' +
                '</div>'
    };
})
33
kevinius

Cool question. Je ne suis pas sûr qu'il existe une méthode intégrée, mais vous pouvez le faire vous-même de manière assez générique.

Vous pouvez accéder à l'élément transcluded en passant le service $ transclude comme ceci:

$transclude(function(clone, $scope) {

Où le clone sera une copie du contenu transclu pré-lié. Ensuite, si vous étiquetez le contenu de l'élément comme ceci:

    <div id="content">
        <div id="content0">{{text}}</div>
        <div id="content1">{{title}}</div>
    </div>

Vous pouvez parcourir le contenu et le compiler comme ceci:

$scope.transcludes.Push($compile(clone[1].children[i])($scope));

Génial! il vous suffit maintenant de mettre le contenu au bon endroit dans votre modèle

     '<div id="transclude0"></div>' +
     '<div id="transclude1"></div>' +

Ensuite, vous pouvez dans votre fonction de lien attribuer correctement le contenu

angular.element(document.querySelector('#transclude' + i)).append(scope.transcludes[i]);

J'ai mis en place un violon vous pouvez jouer avec qui a cette configuration.

J'espère que cela vous a aidé!

21
hassassin

Dans notre projet, nous avons modélisé la trasclusion multi-sites d'après ui: composition, ui: insert, ui: define de JSF 2 (voir i: composition ).

L'implémentation consiste en trois directives simples: ui-template, ui-insert, ui-define (voir angularjs-api/template/ui-lib.js ).

Pour définir un modèle, on écrit le balisage suivant (voir angularjs-api/template/my-page.html ):

<table ui-template>
  <tr>
    <td ui-insert="menu"></td>
  </tr>
  <tr>
    <td ui-insert="content"></td>
  </tr>
</table>

et déclare une directive (voir angularjs-api/template/my-page.js ):

  var myPage = 
  {
    templateUrl: "my-page.html",
    transclude: true
  };

  angular.module("app").
    directive("myPage", function() { return myPage; });

et enfin, pour instancier la directive, il faut écrire (voir angularjs-api/template/sample.html ):

<my-page>
  <div ui-define="content">
    My content
  </div>
  <div ui-define="menu">
    <a href="#file">File</a>
    <a href="#edit">Edit</a>
    <a href="#view">View</a>
  </div>
</my-page>

L'exemple de travail peut être vu via rawgit: sample.html

Voir aussi: Transclusion multisite dans AngularJS