1

I'm facing a problem I can't solve alone with Angular.. I've a news page which will be full of different kind of news (it cans be weather news, flash news, ...). And every news has its own template.

My angular's controller use AJAX to bring in the news in Json, and I'm using ng-repeat to display those news to the user' screen. I'm also using a directive to do so. The thing is, that is a news example bring in by AJAX :

news: {
    title: "sdijfdslfkndc",
    template: "default_template.html",
    ....
}

and in ng-repeat :

<div ng-repeat="info in news">
    <info-directive template="info.template"></info-directive>
</div>

I wish the infoDirective uses to right template defined in the current news. The problem is the info.template attribute is handled as a String and not as an object..

If anyone has an idea about that, I'll thank him so much !

Bye bye !

PS : just for giving you an idea of my infoDirective :

app.directive('infoDirective', function() {
    return {
            restrict: 'E',
            scope: {
              template: '='
            },
            templateUrl: template
    };
});

6 Answers 6

2

The templateUrl attribute in a directive can be a function, taking two parameters : element and attributes and returns a string representing the element's template URL. That way, depending on the attributes, you can display different templates.

app.directive('infoDirective', function() {
    return {
            restrict: 'E',
            templateUrl: function(element,attributes){
                switch(attributes.template){
                     case "template1":
                     return "template.html";
                     //and so on
                }
            }
    };
});

I think it can actually be as simple as this :

app.directive('infoDirective', function() {
    return {
            restrict: 'E',
            templateUrl: function(element,attributes){
                    //if you want to specify the templateURL
                    //directly in the attribute.
                    return attributes.template;
            }
    };
});
Sign up to request clarification or add additional context in comments.

Comments

0

http://onehungrymind.com/angularjs-dynamic-templates/

explains exactly your problem. example:

http://onehungrymind.com/angularjs-dynamic-templates/

and the source:

https://github.com/simpulton/angular-dynamic-templates

In JavaScript everything is a String - the so called JS "Objects", too! But of course you have more handling possibilities with those objects then with pure strings..but always remember: everything in HTML / CSS / JS is a string and will be interpreted as one. So, if you have "problems" with you non-object strings in JS, there are several options you can chose. You can create JS objects via "new ObjectName();" or if you just want HTML code to be interpreted, you can also do it that way:

app.directive('contentItem', function ($compile) {
var imageTemplate = '<div class="entry-photo"><h2>&nbsp;</h2><div class="entry-img"><span><a href="{{rootDirectory}}{{content.data}}"><img ng-src="{{rootDirectory}}{{content.data}}" alt="entry photo"></a></span></div><div class="entry-text"><div class="entry-title">{{content.title}}</div><div class="entry-copy">{{content.description}}</div></div></div>';
var videoTemplate = '<div class="entry-video"><h2>&nbsp;</h2><div class="entry-vid"><iframe ng-src="{{content.data}}" width="280" height="200" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></div><div class="entry-text"><div class="entry-title">{{content.title}}</div><div class="entry-copy">{{content.description}}</div></div></div>';
var noteTemplate = '<div class="entry-note"><h2>&nbsp;</h2><div class="entry-text"><div class="entry-title">{{content.title}}</div><div class="entry-copy">{{content.data}}</div></div></div>';

var getTemplate = function(contentType) {
    var template = '';

    switch(contentType) {
        case 'image':
            template = imageTemplate;
            break;
        case 'video':
            template = videoTemplate;
            break;
        case 'notes':
            template = noteTemplate;
            break;
    }

    return template;
}

var linker = function(scope, element, attrs) {
    scope.rootDirectory = 'images/';

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

    $compile(element.contents())(scope);
}

return {
    restrict: "E",
    link: linker,
    scope: {
        content:'='
    }
};
});

Like i said above, there are multiple ways to reach your target, but i think this way is quite good.

Comments

0

My answer on a similar question might work fine for you:

See other Stackoverflow answer

or the Plunkr directly

Plunkr

app.directive('myDirective', [function(){

return {
    template: '<div ng-include="getTemplate()"></div>',
    restrict: 'E',
scope: {template: '='},
link: function(scope, element, attr, ctrl) {
  var baseURL = 'templates/myDirective.'

  scope.getTemplate = function(){
      baseURL = "" //remove this
      return baseURL + scope.template + ".html"
    };
}
};
}]);

Comments

0

I suggest you create different directives for each type of news. So you would have a directive for weather another for flash news. Each one will have it template and you inject the link function of your directive as if it was a service.

angular.module('somemodule', []).factory('link', function () {

  return function (scope, element, attrs, ctrl) {/*some kind of logic*/}; 

}).directive('flashNews', ['link', function (link){
  return {
            templateUrl: 'flash-news.html',
            link: link
  };
}]).directive('weatherNews', ['link', function (link){
  return {
            templateUrl: 'weather-news.html',
            link: link
  };
}]);

And the ng-repeat:

<div ng-repeat="info in news">
    <div ng-if="info.type.weather">
      <weather-news></weather-news>
    </div>
    <div ng-if="info.type.flash">
      <flash-news></flash-news>
    </div>
</div>

Comments

0

I've got a solution for the problem :

app.directive('infoDirective', function() {

return {
    restrict: 'E',
    scope: {
          info: '=',
    },
    link: function(scope) {
          scope.template = scope.info.template;
    },
    template:"<div ng-include='template'></div>"
};
});

So

<div ng-repeat="info in news.news">
    <info-directive info="info"></info-directive>
</div>

Comments

0

First, I'd like to thank all of you for your answers but there is a thing...

When I do that

<div ng-repeat="info in news">
    <info-directive template="info.template"></info-directive>
</div>

Here, the info.template is handled as a String and I can't get the value of the variable in my directive which is:

app.directive('infoDirective', function() {
    return {
        restrict: 'E',
        templateUrl: function(element,attributes){
                console.log(attributes.template);
                return attributes.template;
        }
    };
});

Even if I use a variables from the loop like $index or use {{ }} to transform variables into proper string, nothing works... For instance, if I write template="{{info.template}}" in the info-directive, in Js I get {{info.template}} for the templateUrl instead of default_template.html...

Do you have an idea?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.