Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to load handlebar template with script tag? Or define handlebar templates programmatically in Ember.js

Simply enough I do not want to define all my handlebar templates in my html file

I tried this

<script type="text/x-handlebars" data-template-name="nav-bar" src="template.handlebar"></script>

But this did not work. Can I not define templates my template programmatically or even just load handlebar files so that I can reuse and also I feel it makes things a bit more maintainable.

I tried just loading them with ajax and appending them to the head, this works fine I can see it there but ember.js doesn't read it after ember has already been loaded and the templates are not defined.

like image 648
timanema Avatar asked Apr 23 '12 03:04

timanema


People also ask

Can you use handlebars in JavaScript?

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.

How do you add templates in your HTML in handlebars?

First, you must create your template in the HTML file. This is created in a standard <script> tag and is a combination of HTML and Handlebar expressions. The template can have any id that you want but the type must be “text/x-handlebars-template” otherwise the script tag will be rendered as JavaScript.

What is handlebars template in Ember?

Ember uses the Handlebars templating library to power your app's user interface. Handlebars templates contain static HTML and dynamic content inside Handlebars expressions, which are invoked with double curly braces: {{}} . Dynamic content inside a Handlebars expression is rendered with data-binding.


4 Answers

Or define handlebar templates programatically in Ember.js

You can define templates programmatically by using Ember.Handlebars.compile, see http://jsfiddle.net/pangratz666/wxrxT/:

Ember.View.create({
    personName: 'Dr. Tobias Fünke',
    template: Ember.Handlebars.compile('Hello {{personName}}')
}).append();​

Or you add compiled templates to Ember.TEMPLATES array, see http://jsfiddle.net/pangratz666/58tFP/:

Ember.TEMPLATES['myFunkyTemplate'] = Ember.Handlebars.compile('Hello {{personName}}');

Ember.View.create({
    personName: 'Dr. Tobias Fünke',
    templateName: 'myFunkyTemplate'
}).append();​

I would recommend to use some tools like Richard Millan stated. Also take a look at interline/ember-skeleton which offers support for compilation of templates.

like image 135
pangratz Avatar answered Oct 17 '22 02:10

pangratz


You can also patch Ember View to load templates on get

Em.View.reopen({
    templateForName: function(name, type) {
        if (!name) { return; }

        var templates = Em.get(this, 'templates'),
            template = Em.get(templates, name);

        if (!template) {
            $.ajax({
                url: 'templates/%@.hbs'.fmt(name),
                async: false
            }).success(function(data) {
                template = Ember.Handlebars.compile(data);
            });
        }

        if (!template) {
            throw new Em.Error('%@ - Unable to find %@ "%@".'.fmt(this, type, name));
        }

        return template;
    }
});

UPDATE: Since Ember 1.0.0-pre.3 this solution probabaly no more work (maybe can be migrated to recent Ember)

like image 45
farincz Avatar answered Oct 17 '22 03:10

farincz


So since I still wanted separate files for my templates and I didn't want to define them in strings in the javascript I hacked this together last night

It is a synchronous lazy loader, it loads all the templates first, then ember and the rest of my code,

        //fake function so that every loads fine will get redefined in application.js
        function initializeApp(){}

        function loadTemplates(){
            var arg = arguments[0],
                next = Array.prototype.slice.call(arguments,1);
            if(typeof arg != 'string'){
                arg()
            }else{
                var scriptObj = document.createElement('script');
                scriptObj.type = 'text/x-handlebars';
                $(scriptObj).attr('data-template-name', arg.replace('.handlebars', '').substring(arg.lastIndexOf('/')+1))
                $.get(arg, function(data){
                    scriptObj.text = data;
                    document.head.appendChild(scriptObj);
                    if(next.length > 0) loadTemplates.apply(this, next);
                });
            }
        }

        function loadScripts() {
            var script = arguments[0],
                scriptObj = document.createElement('script'),
                next = Array.prototype.slice.call(arguments,1);
            scriptObj.type = 'text/javascript';
            scriptObj.src = script;
            scriptObj.onload = scriptObj.onreadystatechange = (next.length > 0) ? function(){loadScripts.apply(this, next)} : function(){$(document).ready(function() {initializeApp()})};
            document.head.appendChild(scriptObj);
        }

        function loadApp(obj){
            loadTemplates.apply(this, obj.templates.concat(function(){loadScripts.apply(this,obj.scripts)}))
        }

        window.onload = function(){
            loadApp({
                templates:
                    [
                        '/javascripts/views/templates/nav-bar.handlebars',
                    ],
                scripts:
                    [
                        'https://maps.googleapis.com/maps/api/js?sensor=false&callback=initializeGoogleMaps',
                        '/javascripts/lib/bootstrap.js', 
                        '/javascripts/lib/rails.js', 
                        '/javascripts/lib/ember.js',
                        '/javascripts/application.js',
                        '/javascripts/views/nav_bar.js',
                    ]
            })
        }

EDIT: I cleaned it up and made it work properly only testing in chrome though

like image 42
timanema Avatar answered Oct 17 '22 03:10

timanema


It is possible, but you will need to precompile your templates first. This will also allow you to include all your templates within one file.

  • If you are using Rails, you can use the ember-rails gem to do it for you.
  • Otherwise you can follow these instructions on how to precompile handlebars

Later on, you will need to include the javascript file.

<script src="path/to/compiled/templates.js" type="text/javascript"></script>
like image 1
Richard Millan Avatar answered Oct 17 '22 02:10

Richard Millan