Last Updated: March 07, 2018
· devers

Variable templates for an AngularJS directive

Sometimes web services and APIs return different data sets for the same type of object. For example, the tumblr API will return a list of posts, but each post type has different data associated with it: text posts have a title and body, while photo posts have captions and images.

Since having different components and directives for each post type doesn't make much sense (especially when they're all displayed in one stream, as on tumblr), it's beneficial to be able to conditionally load a template based on the post type of each individual post.

This code is based on these two articles/posts:

and here is the tumblr API for reference:


angular.module('components', []).
    directive('tumblrPost', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) {

        var getTemplate = function(contentType) {
            var templateLoader,
            baseUrl = '/templates/components/tumblr/',
            templateMap = {
                text: 'text.html',
                photo: 'photo.html',
                video: 'video.html',
                quote: 'quote.html',
                link: 'link.html',
                chat: 'chat.html',
                audio: 'audio.html',
                answer: 'answer.html'

            var templateUrl = baseUrl + templateMap[contentType];
            templateLoader = $http.get(templateUrl, {cache: $templateCache});

            return templateLoader;


        var linker = function(scope, element, attrs) {

            var loader = getTemplate(;

            var promise = loader.success(function(html) {
            }).then(function (response) {

        return {
            restrict: 'E',
            scope: {
            link: linker

news.html (all posts view)

<h1 class="road">News</h1>

<ul id="news">
    <li ng-repeat="tumblrPost in posts">
        <tumblr-post post="tumblrPost"></tumblr-post>

<p class="read-more"><a href="http://{{posts[0].blog_name}}" target="_blank">Read more news</a></p>

text.html (tumblr text post component)

<a href="{{post.post_url}}" target="_blank" class="post-date">{{}}</a>
<div ng-bind-html="post.body"></div>

video.html (tumblr video post component, for comparison)

<a href="{{post.post_url}}" target="_blank" class="post-date">{{}}</a>
<div ng-bind-html-unsafe="post.player[0].embed_code" ui-jq="fitVids"></div>
<div ng-bind-html="post.caption"></div>
Say Thanks

11 Responses
Add your response


Hi Devers,

Thanks for your nice example.
It's great helpful to me.
But, if I don't want to replace the whole html of element, how to?
I have try to using "element.html($compile(element.html())(scope))"
But it doesn't work.
Could you give me some hint?
Thank you.

over 1 year ago ·

Hi Devers,

I have knew how to do.
I just using "$compile(element.contents())(scope)" to replace "element.replaceWith($compile(element.html())(scope))"
Thank you.

over 1 year ago ·

Nice article, I was just working on something like this and this is showing me that Im on the right path.


over 1 year ago ·
Dagu new head

Good read, I really like this pattern. It's pretty sweet!

over 1 year ago ·
0 ip83md6ra82lyvg dkrommnt1hmdkvs dtnym7ka2isj7asibvkdcfrhjej91tu7okc0nh91hnui

Very useful, thanks ;)

over 1 year ago ·

Nice writeup. I'm making an angular directive where I can set the dynamic template. It works. Now I would love to update the template using broadcast events. The code works fine [1] and the new HTML is generated from $compile. The problem is that the directive does not 'refresh' the content. Any idea?


over 1 year ago ·

My Html binding for video template is not working Rest works like a charm :(

over 1 year ago ·
V2iyuyki normal

Using element for accessing the DOM e.g element.find(".child-class") does not work because of the element.replaceWith(). Any cleaner solution?

over 1 year ago ·
V2iyuyki normal

Nevermind. We can do something like this:

var compiled = $compile(; element.replaceWith(compiled); element = compiled; </code> </pre> Thanks for the nice article though.
over 1 year ago ·

Awesome example! Why are you doing both success and then? Looks like almost the same is happening in there?

over 1 year ago ·
Img 20171121 152219

Thank you! This really helped me.

about 2 months ago ·