Skip to content

AngularJS Multi-slot transclusion

I am trying to implement a component in AngularJS 1.5.8 with multi-slot transclusion.

My test works fine if I use a directive, but with a component, it seems like not even the slot is found!.

This is how I declare the component

app.component('asComponent', function() {
return {
  transclude: {
    'title': '?paneTitle',
    'body': 'paneBody',
    'footer': '?paneFooter'
  },
  template: `<h1>I am a component</h1>
              <div style="border: 2px solid red;">
              <div class="title" ng-transclude="title">Fallback Title</div>
              <div ng-transclude="body"></div>
              <div class="footer" ng-transclude="footer">Fallback Footer</div>
            </div>`
}});

app.controller('ExampleController', [ function() {
    var vm = this;
    vm.title = 'Lorem Ipsum';
    vm.link = 'https://google.com';
    vm.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}]);

And here the HTML

 <div ng-controller="ExampleController as $ctrl" class="container">
  <as-component>
      <pane-title>
        <a ng-href="{{$ctrl.link}}">{{title}}</a>
      </pane-title>
      <pane-body>
       <p>{{$ctrl.text}}</p>
      </pane-body>
   </as-component>
 </div>

Official AngularJS documentation says

In AngularJS, a Component is a special kind of directive that uses a simpler configuration which is suitable for a component-based application structure.

If this is the case, then multi-slot transclusion should work perfectly with components as well.

I know I am missing something, but I cannot see what it is!

I have crated a small Plunker with both a directive and a component.

https://plnkr.co/edit/yTMRD4SrH8CWLK4LQEwe?p=info

Thanks

Answer

For components, use an object (not a function):

app.component('asComponent', {
  transclude: {
    'title': '?paneTitle',
    'body': 'paneBody',
    'footer': '?paneFooter'
  },
  template: `<h1>I am a component</h1>
              <div style="border: 2px solid red;">
              <div class="title" ng-transclude="title">Fallback Title</div>
              <div ng-transclude="body"></div>
              <div class="footer" ng-transclude="footer">Fallback Footer</div>
            </div>`
});

Also, you’re missing $ctrl in {{ title }}. It should be:

<a ng-href="{{$ctrl.link}}">{{$ctrl.title}}</a>

Here it is working in a plnkr.