AngularJS directive dynamic templates

67,889

Solution 1

1) You are passing content as attribute in your html. Try this:

element.html(getTemplate(attrs.content)).show();

instead of:

element.html(getTemplate(scope.content)).show();

2) data part of directive is getting compiled so you should use something else. Instead of data-type, e.g. datan-type.

Here is the link:

http://jsbin.com/mibeyotu/6/edit

Solution 2

You can set the template property of your directive definition object to a function that will return your dynamic template:

restrict: "E",
replace: true,
template: function(tElement, tAttrs) {
    return getTemplate(tAttrs.content);
}

Notice that you don't have access to scope at this point, but you can access the attributes through tAttrs.

Now your template is being determined before the compile phase, and you don't need to manually compile it.

Solution 3

You can also do it very straightforward like this:

appDirectives.directive('contextualMenu', function($state) {
    return {
      restrict: 'E',
      replace: true,
      templateUrl: function(){
        var tpl = $state.current.name;
        return '/app/templates/contextual-menu/'+tpl+'.html';
      }
    };
});

Solution 4

If you need to load your template based on $scope variables you can do it 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';
        }
      }
    }
  };
});

Reference: https://coderwall.com/p/onjxng/angular-directives-using-a-dynamic-template

Share:
67,889
Jack
Author by

Jack

Updated on December 20, 2020

Comments

  • Jack
    Jack over 3 years

    I'm trying to make directive with differtent templates based on scope value.

    This is what i done so far which i don't know why doesn't work http://jsbin.com/mibeyotu/1/edit

    HTML element:

    <data-type content-attr="test1"></data-type>
    

    Directive:

    var app = angular.module('myApp', []);
    
    app.directive('dataType', function ($compile) {
    
        var testTemplate1 = '<h1>Test1</h1>';
        var testTemplate2 = '<h1>Test2</h1>';
        var testTemplate3 = '<h1>Test3</h1>';
    
        var getTemplate = function(contentType){
    
            var template = '';
    
            switch(contentType){
                case 'test1':
                    template = testTemplate1;
                    break;
                case 'test2':
                    template = testTemplate2;
                    break;
                case 'test3':
                    template = testTemplate3;
                    break;
            }
    
            return template;
        }; 
    
        var linker = function(scope, element, attrs){
            element.html(getTemplate(scope.content)).show();
            $compile(element.contents())(scope);
        };
    
        return {
            restrict: "E",
            replace: true,
            link: linker,
            scope: {
                content:'='
            }
        };
    });
    
  • Jack
    Jack about 10 years
    Just one question, if i'm doing ng-repeat, for example: ng-repeat="p in people" i can't get value like this: content="p.name". Because this directive is inside ng-repeat cycle.
  • Val Redchenko
    Val Redchenko almost 10 years
    Please note that templateUrl can also be a function
  • sasklacz
    sasklacz almost 10 years
    I'm getting errors when 'show' is called at the end. Work properly without it. Not sure if it's a legacy thing or what.
  • tftd
    tftd over 8 years
    How would you pass $state to the directive?
  • DeBraid
    DeBraid over 8 years
    Best answer if you're looking for simple method to controltemplate based on the route.
  • eloone
    eloone over 8 years
    @tftd like this (function(angular){ angular.module('myModule', ['ui.router']) .directive('myDirective', ['$state', function($state){ return { templateUrl: 'tpl.html' }; }]); })(window.angular);
  • Shikha thakur
    Shikha thakur almost 8 years
    hi, When i implemented the same code as yours i am getting error as angular.js:13708 Error: [$compile:tpload] Failed to load template: <ng-include src="getTemplateUrl()"/> (HTTP status: 404 Not Found) Could you please help me out with this
  • Karolis.sh
    Karolis.sh almost 8 years
    Could you provide directive controller code? My guess is that directive's scope doesn't have the getTemplateUrl function and browser tries to load undefined template.
  • Gary
    Gary almost 8 years
    @Slaven Tomac I am trying to add form elements dynamically. But when adding items with ng-repeat and ng-options dynamically it does not show the repeat items. Just the static HTML. Here is what I mean to say. plnkr.co/edit/JOzTWB6tuyilCJ8Rj37Q Any issues with the code or can ng-repeat be also compiled in the template.
  • Nicu Surdu
    Nicu Surdu over 7 years
    This doesn't work if your directive is using transclude, but nice approach anyway ;)
  • Tiberiu C.
    Tiberiu C. about 7 years
    when templateUrl is specified like a function that function receives two arguments, the first is the element and the second is the scope. So to get hold of the isolated scope is easier to use the one from the callback : {templateUrl : function($el, $scope) { return '..'+$scope.name+'..'}}
  • Danny Coulombe
    Danny Coulombe almost 7 years
    @Tiberiu C. The second argument is not the $scope, but the attributes.
  • Sotiris Zegiannis
    Sotiris Zegiannis over 3 years
    the tAttrs.content doesnt return the actual value of the content, just the hmtl template value.