Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use Angular transclusion

I am reading angular transclusion which some examples from this page: http://www.c-sharpcorner.com/UploadFile/17e8f6/transclusion-in-custom-angularjs-directive/

This page gave useful examples. However I wonder when to use transclusion. The original example:

<user-post user-name="{{user.Name}}" post-details="post" ng-repeat="post in user.Posts">
    <user-likes post-likes-count="{{post.Likes.length}}"></user-likes>
</user-post>

This is HTML template of userPost directive:

<div class="panel panel-default panel-primary">
    <div class="panel-heading">
        <h5><strong>{{userName}}</strong></h5>
    </div>
    <div class="panel-body">
        <img ng-src="{{postDetails.Content}}" alt="Image" class="img-responsive" />
    </div>
    <div class="panel-footer" ng-transclude>
    </div>
</div>

But I can rewrite it without transclusion:

<div class="panel panel-default panel-primary">
    <div class="panel-heading">
        <h5><strong>{{userName}}</strong></h5>
    </div>
    <div class="panel-body">
        <img ng-src="{{postDetails.Content}}" alt="Image" class="img-responsive" />
    </div>
    <div class="panel-footer">
        <user-likes post-likes-count="{{likeCount}}"></user-likes>
    </div>
</div>

I want to know the best cases to use transclusion?

like image 247
Leo Vo Avatar asked Oct 22 '25 06:10

Leo Vo


2 Answers

To understand Transclusion, and when/how to use it, you have to understand a bit about the DOM you are trying to represent, and how angular directives play a role in the DOM.

Specifically, this is related to directives which are Elements (restrict: 'E'). Let's take the most basic HTML for a directive we can possibly take:

.directive('myDirective', function(){
  return {
    restrict: 'E',
    template: '<div></div>' +
              '<div></div>'
  };

Usage:

<my-directive>Some Content</my-directive>

Now, here is the question that is the key to understanding transclusion:

Where does Some Content end up?

In this case, Some Content has nowhere to go. When the directive is injected into the DOM, it is replaced by the template. The template doesn't know about Some Content, and has no place to put it, and therefore it will not be output in the final DOM.

Now, adding transclusion, we can solve this problem.

.directive('myDirective', function(){
  return {
    restrict: 'E',
    transclude: true,
    template: '<div></div>' +
              '<ng-transclude></ng-transclude>'
  };

Now, when the DOM is compiled, Some Content has a place to go. Transclusion allows the inner content of the element to be placed in the template, in the spot where the ng-transclude directive exists.

Now, transclusion can get very tricky, especially when you have a directive nested in the inner content of another directive, but it can be very powerful. However, if your directive will not have content inside the element in your markup, transclusion isn't necessary. There are many more ways to make use of transclusion, but at their core, they all ultimately come back to this concept.

like image 82
Claies Avatar answered Oct 25 '25 00:10

Claies


You would use transclude to inject bunch of html into your directive. The idea of creating directive is so that you have reusable bunch of code that you can use within various parts of your application. Transclusion allows you to further customize the content of your directive from the template.

Following your example, the idea to create user-post directive with transclusion would be that your user post might not have exact same content throughout different part of your application.

If you notice in template 2, I can add some extra HTML to accommodate different content in the directive.

Template 1:

<user-post user-name="{{user.Name}}" post-details="post" ng-repeat="post in user.Posts">
    <user-likes post-likes-count="{{post.Likes.length}}"></user-likes>
</user-post>

Template 2:

<user-post user-name="{{otherUser.Name}}" post-details="post" ng-repeat="post in otherUser.Posts">
    <user-likes post-likes-count="{{post.Likes.length}}"></user-likes>

    // this directive might loop through post.comments and display a list
    // of comments on the post.
    <user-comments post-comments="{{post.comments}}"></user-comments>

    <p>some other customize html</p>
</user-post>

Now I have 2 user posts in my application. One has posts and user likes and the other has posts with user likes and comments.

like image 44
Subash Avatar answered Oct 24 '25 23:10

Subash