AngularJS : transcluding multiple sub elements in

2020-05-19 06:57发布

I am Fairly new to Angular but have been reading quite a lot. I was reading about ng-transclude at http://docs.angularjs.org/guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive and I think I understand properly what it does.

If you have a directive that applies to an element that has content inside it such as in

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

It will allow you to tag an element within the directive's template with ng-transclude and the content included in the element would be rendered inside the tagged element.

so if the template for myDirective is <div>before</div><div ng-transclude></div><div>after</div> it would render as beforedirective contentafter.

this is all o.k. my Q is is it possible to somehow pass more then a single block of html into my directive?

e.g.

suppose the directive usage would look like this:

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

and have a template like:

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

render as

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

?

(thinking to myself) Could I somehow bind the HTML value of a node to the model so that I will be able to use it in such a way without calling it "transclude" ...

Thanks

3条回答
戒情不戒烟
2楼-- · 2020-05-19 07:03

Cool question. I'm not sure there is a built in way, but you can do it yourself in a pretty generic way.

You can access the transcluded element by passing in the $transclude service like this:

$transclude(function(clone, $scope) {

Where clone will be a copy of the pre-linked transcluded content. Then if you label the content in the element like this:

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

You can loop over the content and compile it like this:

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

Great! now you just need to put the content in the correct place in your template

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

Then you can in your link function assign the content correctly

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

I set up a fiddle you can play with that has this set up.

Hope this helped!

查看更多
祖国的老花朵
3楼-- · 2020-05-19 07:03

In our project we have modeled multi site trasclusion after JSF 2's ui:composition, ui:insert, ui:define (see ui:composition).

Implementation consists of three simple directives: ui-template, ui-insert, ui-define (see angularjs-api/template/ui-lib.js).

To define a template one writes the following markup (see angularjs-api/template/my-page.html):

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

and declares a directive (see angularjs-api/template/my-page.js):

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

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

and finally, to instantiate the directive one needs to write (see 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>

The working sample can be seen through rawgit: sample.html

See also: Multisite Transclusion in AngularJS

查看更多
迷人小祖宗
4楼-- · 2020-05-19 07:16

Starting Angular 1.5, it's now possible to create multiple slots. Instead of transclude:true, you provide an object with the mappings of each 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>'
    };
})
查看更多
登录 后发表回答