A
ngTransclude
directive is a thing I often found in many examples, yet I think it is not well explained in the official docs. I was never really sure how to use it, and I am sure I am not the only one. As I found, the general concept is not difficult, but documentation, which uses lots of big words, makes it hard to understand. I decided to create a quick user guide to describe how you can use ng-transclude
with a short but expository example.To explain transclusion in one sentence you could say that it is a way of including content from one template to another. Imagine a simple situation. You have a directive for a card with some data. It contains three elements — header, content and button. The template can look like this:
<div class="card">
<h1 class="header">{{header}}</h1>
<div class="content">{{content}}</div>
<button
type="submit"
class="button"
ng-click="buttonAction()">
{{buttonText}}
</button>
</div>
This HTML template allows you to use this card everywhere you want. This requires a code for a directive, for example, something like this:
(function() {
'use strict';
angular
.module('app.card')
.directive('Card', Card);
function Card() {
return {
restrict: 'E',
replace: true,
scope: {
header: '@',
content: '@',
buttonAction: '&',
buttonText: '@'
},
templateUrl: 'card.html'
};
}
})();
It is very simple; data binding allows you to bind attributes values to this template. A
header
, content
and buttonText
are bound as text in the places where corresponding expressions occur. You can also pass a function to a button using buttonAction
. It can be done as simple as this:<card
header="Hello"
content="Do you want to continue?"
button-text="Nope"
button-action="$ctrl.close()">
</card>
It is a very good solution for making consistent cards in every place it is needed. When you want to change how the card looks like to the user, just apply changes to the template and you will get a discernible effect in every place that this directive is used.
Although this directive gives you a little flexibility, it doesn’t really allow you to add something more to it. This doesn’t let us use HTML formatting in the content. Imagine that instead of simple text binding, you want now to add something more sophisticated to your card content. This is what transclusion is used for, to nest the content as HTML inside it. The brilliance of transclusion is that everything you put inside your directive tag can be displayed in a particular place in your template. As an example, you want to add a simple table to the content. First, a template should be changed.
<div class="card">
<h1 class="header">{{header}}</h1>
<div class="content" ng-transclude="cardContent"></div>
<button
type="submit"
class="button"
ng-click="buttonAction()">
{{buttonText}}
</button>
</div>
The same changes are required in the directive, now the content will be transcluded:
(function() {
'use strict';
angular
.module('app.card')
.directive('Card', Card);
function Card() {
return {
restrict: 'E',
replace: true,
transclude: {
cardContent: 'cardContent'
}
scope: {
header: '@',
buttonAction: '&',
buttonText: '@'
},
templateUrl: 'card.html'
};
}
})();
And now you can use it as you want. You can put whatever inside your directive html tag and it will be displayed inside a
div
with cardContent
transclusion. You can add a simple table inside:<card
header="Table"
button-text="Close"
button-action="$ctrl.close()">
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</card>
It will result with this HTML code in the end:
<div class="card">
<h1 class="header">Table</h1>
<div class="content">
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</div>
<button
type="submit"
class="button"
ng-click="$ctrl.close()">
Close
</button>
</div>
As you see values of every attributes are bound to selected elements and table was inserted to content
div
.The transclusion directive is something that is not described properly with AngularJS docs, but with a little explanation and real-life example, it becomes very easy. It allows you to not needlessly repeat yourself when creating directives in your application and to make your templates more versatile. I really recommend using it often across your application directives.
This story was originally published on my Medium page on Nov 14, 2017 and had 1.4K views when moved to my Hackernoon page.