Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handlebars, loading external template files

My goal is to put all my Handlebars templates in a single folder, as so:

templates/products.hbs templates/comments.hbs 

I found this snippet in a few places via a cursory Google search, which apparently will load in Handlebar templates in external files, which makes much more sense than putting a bunch of templates in a single index file.

(function getTemplateAjax(path) {     var source;     var template;      $.ajax({         url: path, //ex. js/templates/mytemplate.handlebars         cache: true,         success: function(data) {             source    = data;             template  = Handlebars.compile(source);             $('#target').html(template);         }                    });          })() 

The problem is, I don't understand this function or how to use it. Why is the whole function wrapped in parentheses and then made a function call? e.g. (function x() { ... })() I don't know what this is doing.

And if I'm not mistaken, looks like $('#target') is hardcoded when it shouldn't be. Furthermore, isn't this supposed to set a data variable somewhere so the variables referenced in the template will work?? Seems the correct function should be:

function getTemplateAjax(path, target, jsonData) {   var source;   var template;    $.ajax({     url: path, //ex. js/templates/mytemplate.handlebars     cache: true,     success: function(data) {       source    = data;       template  = Handlebars.compile(source);       $(target).html(template(jsonData));     }                  });          } 

Side note: if someone could point me to a better template engine, one that actually natively supports external template files, and is better organized than Handlebars, I'd be eternally grateful.

Another issue: I can't actually name my files mytemplate.hbs, because when the Ajax call happens, it sees it as a binary file and it comes through as binary. I suppose this is an issue of setting the server's mime type for .hbs to text/html or text/plain, but the issue is that this is a Grunt server and I'm not sure how to change its mime types.

like image 251
CaptSaltyJack Avatar asked Oct 30 '14 01:10

CaptSaltyJack


People also ask

How do I compile handlebars templates?

Precompiling Templates Inside NodeJS If you wish to precompile templates from inside NodeJS--without invoking "handlebars" from the command line--that can be done with Handlebars. precompile. Transmit the string result of this function to your clients, and they can in turn parse that with Handlebars. template.

Is handlebars a template engine?

Handlebars is a simple templating language. It uses a template and an input object to generate HTML or other text formats.

What is a handlebar template?

Handlebars. js is a Javascript library used to create reusable webpage templates. The templates are combination of HTML, text, and expressions. The expressions are included in the html document and surrounded by double curly braces. These expressions are placeholders for content to be inserted by our Handlebars.

Are handlebars backend?

Handlebars is popular for both back-end and front-end templating. For example, the popular front-end framework Ember uses Handlebars as the templating engine. Handlebars is an extension of the Mustache template language, which is mostly focused on simplicity and minimal templating.


1 Answers

The code is wrapped in an IIFE (Immediately Invoked Function Expression), which means the function is executed immediately. That's what the following means:

(function x() {   console.log('hello'); })(); 

You can also do:

(function() {   console.log('hello'); }()); 

IIFEs are commonly used to create a "private" scope for a bit of code so that it plays nice (doesn't conflict) with anything else.


The second function you provided makes more sense and perhaps the first one must have been just an example.
Handlebars allows you to **precompile** your templates so you don't have to compile them at run-time. Also this way you don't have to make extra HTTP requests just to load the template(s).

For example if I have the following project structure - (note that my models, collections, and views are all within main.js just for this example and all my .js files are in my root directory):

├── Gruntfile.js ├── handlebars-v2.0.0.js ├── index.html ├── main.js ├── package.json └── templates     └── todo.handlebars 

My `todo.handlebars` looks like so - just html with Handlebars syntax:
<h3>{{title}}</h3> <p>Created by: {{author}}</p> 

To precompile my template I would do the following in the command line (*you have to install the handlebars precompile script first with: `npm install -g handlebars`*):
> handlebars templates/todo.handlebars -f todo.tpl.js 

Now my project structure looks like so:

├── Gruntfile.js ├── handlebars-v2.0.0.js ├── index.html ├── main.js ├── package.json ├── templates │   └── todo.handlebars └── todo.tpl.js 

You'll see that a todo.tpl.js file has been added to my root directory. I could have named it something different if I wanted to as long as the extension is a .js because the file contains valid JavaScript code. Also I could have specified a different directory to output it to. Remember that the todo.tpl.js file is the actual template that your Backbone View will use. You write your HTML in todo.handlebars and compile it as todo.tpl.js.


Now that I have the `todo.tpl.js` file I can use Grunt to maybe concat all my JS template files into a `all_templates.js` file or I can reference each file directly in my HTML like so:
  <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>   <script src="http://documentcloud.github.io/underscore/underscore-min.js"></script>   <script src="http://documentcloud.github.io/backbone/backbone-min.js"></script>   <script src="handlebars-v2.0.0.js"></script>   <script src="todo.tpl.js"></script> <!-- My Template for a Todo item -->   <script src="main.js"></script> 

In my Backbone View, which in my case lives inside my *main.js* file, I would get the template like so:
var TodoView = Backbone.View.extend({   tagName: 'li',     className: 'todo-item',   events: {    },    // You can grab your template function with the name you chose when   // you precompiled it from: `Handlebars.templates`   template: Handlebars.templates.todo,    initialize: function(options) {     this.listenTo(this.model, 'change', this.render);   },    render: function() {     this.$el.html(this.template( this.model.toJSON() ));     return this;   } }); 

And you're done! More info here:
  • http://handlebarsjs.com/precompilation.html (broken; see next link)
  • https://handlebarsjs.com/api-reference/compilation.html#pre-compilation
  • https://www.npmjs.org/package/handlebars
  • http://code.tutsplus.com/tutorials/introduction-to-handlebars--net-27761 (read where it talks about precompiling)
like image 109
istos Avatar answered Oct 14 '22 18:10

istos