March 2, 2016

Angular 1.5 Multi Slot Transclusion

Angular 1.5 Multi Slot Transclusion

Transclusion is one of the most useful features when it comes to writing reusable Angular directives. Even if you never heard of what it is, you might have used transclusion before without knowing it. The version 1.5 of AngularJS adds a long awaited feature: Multi Slot Transclusion, that allows us developer to build ever more flexible API’s for our directives.

I’m not going through the whole concept of transclusion, there are a lot of posts in the internet (see Chapter ‘Further Reading’) that cover this topic.

 

Classic Transclusion in Angular 1.4 and below

typically you would use transclusion to let the user of your directive insert his custom HTML into your directive.

Given you have a markup such as the following:

and two directive definitions like

The two directives list and list-item render the following snippet:

The Problem

Typically you start to run into limitations pretty soon. Lets imagine you want to create a directive similar to the example above:

  • show the title of a list-item
  • display either a icon as a css-class or a img-tag on the left
  • show some textual content

of course you could implement this by introducing one or two more directives and start nesting them inside each other, but in this case lets imagine we want to stick with only the two existing directives list and list-item

The Solution

Multi Slot Transclusion is here to help deal with this kind of scenarios. With very little modifications to the directives created above we can easily add the desired behavior. IMHO the readability of the new directive we’re about to create is improved greatly compared to classic transclusion – especially from the point of view of a consumer of the directive.

As you can see we added a few more lines of code we’re about to cover now:

in line 2-6 we define a list-item that still has an attribute title="Football" as it has before. The additions we made start to appear inside the list-item-tags where we added two more elements.
On the one hand we added a content element that was the content in the first example that was transcluded in the list-item directive. We now have a more semantical way of expressing what kind of HTML is transcluded here.
On the other hand there is a icon element that shall represent our image/icon that we want to display on the left of the list. As we can see this element can have its own HTML elements inside the icon-tags. In this example a placeholder image.
Whats important to note here is that the order of the elements inside the list-item does not matter. What matters is the name of the elements inside it.

How does Angular know where to place the transcluded content you might wonder.

Again we made minor adjustments to the directive from the first example. Mainly we redefined the transclude-property of the directive definition. Where we previously just wrote transclude: true we can now specify an object. The key (left part of the key-value) of the object is the name that is used internally in this directive to let angular know where we want the transcluded content to be inserted. you can see this in the template definition of the directive. In line 15 we say
<span ng-transclude="iconSlot"></span> and tell angular to insert the icon here.
same applies for the contentSlot, that gets inserted in line 18.

So the key of the transclude key-value is the internal name of the HTML-snippet. So whats the value then? We already saw what it is. The value is the name of the element in the template that uses our list-item directive.

the content-element is the name that is used in the directive’s transclusion definition: transclude: {'contentSlot': 'content'}
Thats all the magic that happens.

A few More thing to note are:

  • classic transclusion still works the way it always did. An upgrade to Angular 1.5 wont break your application, but gives you the opportunity to use Multi Slot Transclusion.
  • you can use ng-transclude-slot as an alias for ng-transclude
  • you can use ng-transclude as an attribute and an element
  • you can specify default transclusion content, take a look at the directive definition in our 2nd example

If you want to, you can take a look at this Plunkr and play a little with it, to get familiar with the newly introduces syntax.

Further Reading

  1. Transclusion explained
  2. Classic AngularJS Transclusion
  3. AngularJS 1.5 Multi Slot Transclusion
  4. AngularJS Docs about Transclusion
  5. Stackoverflow discussion about transclusion

 

Kai Henzler
Developer at thecodecampus </>


Leave a Reply

Add code to your comment in Markdown syntax.
Like this:
`inline example`

```
code block
example
```

Your email address will not be published.