April 4, 2016

Transclusion Part 1 - Basic Transclusion

Transclusion fills an important role in angular, and yet it remains one of the most difficult to understand concepts in the framework. Many articles have been written to try to break down the problem of how transclusion works. I want to take this one step further by introducing several use cases in which we have found transclusion to be a powerful tool. In this part, I’m going to go over the basics of transclusion in angular 1.x and its counterpart in angular 2. I will follow this up with an in-depth look at several different more powerful use cases.

There are a number of exciting changes coming down the pipe in terms of transclusion. First, in Angular 2, the entire system behind transclusion will be overhauled for something that is much easier to use for simple use cases. However, in the more immediate future, the angular team is looking to add support for multi-transclusion in the 1.5 release. We’ll explore the latter of these in greater detail in part 2.

I want to begin with a simple definition. What is transclusion? Wikipedia gives us the following definition: “In computer science, transclusion is the inclusion of a document or part of a document into another document by reference.” So essentially transclusion is a way to inject snippets from outside into a component. This can be extremely useful for a variety of different components. If we want to build a reusable container component, transclusion is essential for accomplishing this. The user should be able to instantiate the component with an html tag, and then specify the content that should be placed inside of the container by nesting it inside of the container tag.

<my-container>
	This is the content for the container
</my-container>

In angular 1.x, simple transclusion, as outline above, is actually relatively easy to do. First, we need to specify in our directive definition that we want to use transclusion in our component. We can do this by setting transclude: true in the directive definition object. Once transclusion is enabled, we can inject the content inside of the component’s tag by using the ng-transclude directive.

<div style=”color: red” ng-transclude></div>

The result is that the contents of the div will be replaced with the contents of the container tag.

<my-container>
	<div style=”color: red”>
    	This is the content for the container
    </div>
</my-container>

This allows us to build a simple container component with very little effort. Once you go beyond the base use case however, the topic becomes much more complex. We will cover multi-transclusion in the next section using a simple card component as a use case.
As I mentioned before, angular 2 is doing a major overhaul of the transclusion system as a whole. While this may be daunting for someone who has invested a lot of time into learning how transclusion works in angular 1, this is actually a good thing. The new system for transclusion will be simpler and easier to use. In addition, angular is getting on board with the upcoming web components standards by aligning their techniques with web component concepts. Because of this, angular now refers to the process as projection instead of transclusion, and we will use that term when referring to the angular 2 equivalent.

For the simplest use-case, projection functions very similar to transclusion in angular 1.x except that it does not need to be specifically enabled in the component definition. Also, instead of ng-transclude, we now use the tag ng-content. For our container example, this now becomes as simple as adding an ng-content tag to our template.

<div style=”color: red”><ng-content></ng-content></div>

Note that we can no longer apply the style directly to the ng-content tag, as we did above. However, the result is the same.

<my-container>
	<div style=”color: red”>
	    This is the content for the container
	</div>
</my-container>

We no longer have to specify transclude: true in the component definition for myContainer. This is a relatively simple change for the case of basic transclusion. However, we will see how angular 2 transclusion makes more complicated use cases much simpler in the next part of this series.

To summarize, I have provided a brief introduction to the concepts of transclusion and projection in angular 1 and 2, and the differences between the two. Both concepts fill the same role, and are easy to use for simple use cases. In the next part, I will dig into how to solve more complicated use cases such as building a simple card component by using multi-transclusion/projection. We will explore the ugly solution that is required for angular 1.4, how this is simplified to a large degree in angular 1.5, and how the angular 2 projection system makes this much easier.

For a brief introduction of the new angular 2 component syntax: http://blog.ionic.io/angular-2-series-components/