onjxng
Last Updated: February 25, 2016
·
46.64K
· gsans
10299858 466346363511370 800354043 a

Angular - Directives: using a dynamic template

AngularJs Meetup South London Collection | this article

Directives are a very powerful concept in Angular. Let's say we want to create a directive to display user profiles. The final directive should be used like this

<profile data="{name:'John', type='twitter'}"/>
<profile data="{name:'Maria', type='facebook'}"/>

Internally we want the directive to change the template being used based on the user type. In order to setup a template for your directive you can use template or templateUrl options.

This would be the initial version

Profile directive (using template)

.directive("profile", function() {
  return {
    template: '<h1 ng-bind="user.name"></h1>',
    scope: {
        user: '=data'
    },
    restrict: 'E'
  };
});

This works fine but still does not take into account the type. We can move the template to a file first and use templateUrl.

Profile directive (using templateUrl)

.directive("profile", function() {
  return {
    templateUrl: 'profile.tpl.html',
    scope: {
        user: '=data'
    },
    restrict: 'E'
  };
});

In order to implement the dynamic template we can't use any of the two so we have to resort to another approach using ng-include. We can't use templateUrl as it has no access to $scope.user.type.

templateUrl: function() { return "profile.tpl.html";} //no access to $scope

Dynamic template using ng-include

.directive("profile", function() {
  return {
    template: '<ng-include src="getTemplateUrl()"/>',
    scope: {
        user: '=data'
    },
    restrict: 'E',
    controller: function($scope) {
      //function used on the ng-include to resolve the template
      $scope.getTemplateUrl = function() {
        //basic handling
        if ($scope.user.type == "twitter")
          return "twitter.tpl.html";
        if ($scope.user.type == "facebook")
          return "facebook.tpl.html";
      }
    }
  };
});

Demo code: link

AngularJs Meetup South London Collection | this article

Say Thanks
Respond

8 Responses
Add your response

17628
None

Thanks for this great tutorial! I was looking for exactly this feature. Many many thanks.
Best regards
Wim

over 1 year ago ·
17972
None

Why not using ngSwitch?

over 1 year ago ·
17973
10299858 466346363511370 800354043 a

You could use ngSwitch too but it wouldn't be a dynamic template then.

over 1 year ago ·
21219
0 dv0vdv6gesrlkulw7kgqdmpyhz6lrflw7ciodmn cg zfw itpfm jhs69qvphxb2njwgoewq0nv

Hi, and thanks for the post.

I used your code to get dynamic template but I am getting an error despite the code is working.
Do you know what it is?

Error:
At Chrome = TypeError: undefined is not a function at forEach.attr
At Firefox = Error: element.setAttribute is not a function

You can see more datails on: http://stackoverflow.com/questions/30668661/angular-directive-with-dynamic-template

over 1 year ago ·
21220
10299858 466346363511370 800354043 a

It seems is browser related as shows DOM manipulation. Is pointing to attributes. Maybe it doesn't like data-content attribute?

over 1 year ago ·
21226
0 dv0vdv6gesrlkulw7kgqdmpyhz6lrflw7ciodmn cg zfw itpfm jhs69qvphxb2njwgoewq0nv

I didn't understand your point. What do I have to change?

over 1 year ago ·
21228
10299858 466346363511370 800354043 a

I created a little test and it worked fine for me. I believe your issue is in your data and not in the approach shown here.

over 1 year ago ·
21231
0 dv0vdv6gesrlkulw7kgqdmpyhz6lrflw7ciodmn cg zfw itpfm jhs69qvphxb2njwgoewq0nv

OK gsans, I'll make other tests. Thank you for your help.

over 1 year ago ·