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

21,070

Solution 1

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.

Solution 2

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)

Solution 3

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

Solution 4

If you load your templates into the DOM before loading Ember, then you don't need to compile or register your templates. Ember will come along after and do it for you.

Here is an article showing how:

http://weboriented.wordpress.com/2012/09/02/loading-handlebars-templates-in-ember-using-curl-js/

Solution 5

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.

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

<script src="path/to/compiled/templates.js" type="text/javascript"></script>
Share:
21,070
timanema
Author by

timanema

Updated on July 09, 2022

Comments

  • timanema
    timanema almost 2 years

    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.

  • timanema
    timanema about 12 years
    Ah yes! this is the kind of stuff I was looking for kind of
  • thesmart
    thesmart over 10 years
    I don't believe you can compile Ember.Handlebars w/ standard handlebars tools.
  • Alp
    Alp over 10 years
    Does anyone know how to do this with recent Ember.js?
  • Ashburton88
    Ashburton88 over 9 years
    Ember CLI is another great option.
  • rr-
    rr- over 9 years
    Note that synchronous requests are now considered obsolete: xhr.spec.whatwg.org/#sync-warning
  • Paul
    Paul over 9 years
    The syntax has slightly changed in the latest version of Ember (v1.8 at time of writing) to {{view.personName}}. Checkout my jsbin: emberjs.jsbin.com/soqore/2/edit