Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm learning AngularJS and I have a bit of a problem with directives. I don't like how they look. Specifically, I don't like when there is a lot of html in the middle of the javascript. Look at the following example:

myApp.directive("myDir", function() {
  return {
    restrict: "E",        // directive is an Element (not Attribute)
    scope: {              // set up directive's isolated scope
      name: "@",          // name var passed by value (string, one-way)
      amount: "=",        // amount var passed by reference (two-way)
      save: "&"           // save action
    },
    template:             // replacement HTML (can use our scope vars here)
      "<div>" +
      "  {{name}}: <input ng-model='amount' />" +
      "  <button ng-click='save()'>Save</button>" +
      "</div>",
    replace: true,        // replace original markup with template
    transclude: false,    // do not copy original HTML content
    controller: [ "$scope", function ($scope) { …  }],
    link: function (scope, element, attrs, controller) {…}
 }
});   

Having html code rendered from a javascript string seems so old school. :D I've seen that there is the templateUrl to use, but that loads a full page, and if the directive is small, this seems far from optimal.

What I would like to do is to load a html file with loads of named templates in it. Is that easy, and if not, anyone have a successful pattern for this?

Could anyone point me in the right direction? I really don't want to start writing html within my code after all these years of separation of code and html, and I don't want to start my career as AngularJS developer by extending the framework. ;)

Or am I using directives wrong? (The example code above is from a tutorial I read)

share|improve this question

2 Answers 2

up vote 2 down vote accepted

Yes of course you can do it. You can create ng-template script sections with any html page. See this fiddle i created for editable directive http://jsfiddle.net/cmyworld/6gMXL/

If you add scripts such as

<script type="text/ng-template" id="editable-template"> </script>

you can reference them in directive definition using templateUrl.

share|improve this answer
    
Thanks, this really pointed me in the right direction. Using your example and <div ng-include="'/templates/mytemplate.html'"></div> I could put the templates in a separ –  Aspelund Jan 16 at 7:20

You've got the majority of it right.

I'm not sure what you mean by "whole page", though.

Angular works on template "partials", the same way a server-side template might...

// currentDirective = {.....
templateUrl : "/templates/current-directive.html"
// ...}; return currentDirective;

Meanwhile, the contents of that file are just:

<div class="current-directive>
    <div><span>{{ property }}</span><button ng-click="method(arg)">click</button></div>
</div>

Yes, that seems like a waste.
It's a whole round-trip just for a few HTML elements.

But, angular also caches that directive template.
Future instances of the directive result in in-memory reconstruction of the template, making it lighter than a lot of other solutions out there (only loading a template when it's actually going to be used, and only loading it one time, rather than loading a whole app's worth of templates, if you're only going to use two pages worth of widgets, or hitting the server for regenerated templates over and over).

That said, if you do have a strong case for batching templates together, what you can do is have your server batch all of the templated strings ''... and all of the URLs that they should live at... into an array of objects, in a batch-process:

/templates my-template.html other-template.html another-template.html

becomes

[{
    url : "/templates/my-template.html",
    template : '<div>{{prop}}</div>;
 } /*,...*/]

Then, what you can do is request the $templateCache object.
I'm not sure exactly what it is (service/factory), and therefore, I'm not sure exactly when it needs to be run, but basically, when everything is getting set up.

If that JS array is printed into the page, dynamically, then you can just say:

angular.module("myApp").run(function ($templateCache) {
    templates.forEach(function (cached) {
        $templateCache.put(cached.url, cached.template);
    });
});

This happens before you're actually inside of Angular (ie: before window.load).

If you were to get that array as a JSON package, from an HTTP request, then you'd need to manually bootstrap Angular, afterward, as it's too late to use ng-app, automatically.

angular.bootstrap(document.documentElement, ["myApp"]);

The other alternative is to use <script> tags on the first page.

<script type="text/ng-template" id="/templates/my-template.html">
    <div >{{ prop }}</div>
</script>

Angular will now automatically cache that template to that URL. All of your templates now need to be in script tags, and embedded on the page, before the window.onload event, and within the confines of the ng-app boundaries.

Downside being you're now back to having the user download absolutely everything, to start.

In order to use these pre-cached templates, all you need to do is inject $templateCache into a directive (top-level definition for the directive, rather than into a scope/controller is fine), and then call .get(url)

// currentDirective = { ...
        template : $templateCache.get("/templates/current-directive.html"),
// }; return directive

No extensions needed.
Just be aware that both using "templateUrl", and using $templateCache.get(url) have their various downsides.

share|improve this answer
    
Why would you use template : $templateCache.get in the directive? If it's in the cache then using templateUrl will get it form there. –  zeroflagL Jan 15 at 9:03
    
Thanks for the answer, it helped me understanding angularjs. –  Aspelund Jan 16 at 7:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.