Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Ember.js reference Grunt.js precompiled Handlebars templates?

I've been exploring Ember.js, along with Grunt.js but I can't understand how Ember.js is able to find and use precompiled Handlebars templates. Right now my Gruntfile.js looks like this:

module.exports = function(grunt) {

// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
handlebars: {
  compile: {
    files: {
       "js/templates.js": "templates/*.hbs",
    }
  }
}
});

// Load the plugin that handles the handlebars compiling
grunt.loadNpmTasks('grunt-contrib-handlebars');

// Default task(s).
grunt.registerTask('default', ['handlebars']);

};

And my app.js Ember views are declared like so (routes and controllers are left out):

App.LogoView = Ember.View.extend({
  templateName: 'logo',
  classNames: ['logo']
});

App.TabsView = Ember.View.extend({
  templateName: 'tabs',
  classNames: ['tabs']
});

App.TabView = Ember.View.extend({
  classNames: ['content'],
  tabPositions: {
    tab1: {
      width: '90px',
      left: '82px'
    },
    tab2: {
      width: '180px',
      left: '172px'
    },
    tab3: {
      width: '271px',
      left: '263px'
    }
  },
  animateTab: function() {
    var left, tab, width;
    tab = this.get('templateName');
    width = this.get('tabPositions.' + tab + '.width');
    left = this.get('tabPositions.' + tab + '.left');
    Ember.run.next(function() {
      $('div.tabs').removeClass('tab1 tab2 tab3');
      $('div.tabs').addClass(tab);
      $('div.slider div.foreground').stop().animate({
        'width': width
      }, 1000);
      $('div.slider div.handle').stop().animate({
        'left': left
      }, 1000);
    });
  },
  didInsertElement: function() {
    this.animateTab();
  }
});

App.SliderView = Ember.View.extend({
  templateName: 'slider',
  classNames: ['slider']
});

App.Tab1View = App.TabView.extend({
  templateName: 'tab1'
});

App.Tab2View = App.TabView.extend({
  templateName: 'tab2'
});

App.Tab3View = App.TabView.extend({
  templateName: 'tab3'
});

And this is my file structure:

--/
  |--js/
    |--app.js
    |--ember.js
    |--handlebars.js
    |--jquery.js
    |--templates.js
  |--templates/
    |--application.hbs
    |--logo.hbs
    |--slider.hbs
    |--tab1.js
    |--tab2.js
    |--tab3.js
    |--tabs.js
  |--Gruntfile.js
  |--index.html
  |--package.json
  |--server.js

So I'm using the <script type="text/x-handlebars" data-template-name="slider"> syntax in my index.html file to reference templates by name and that works fine. What I don't understand, is how Ember.js is supposed to use the precompiled templates.

Right now, I'm using Grunt.js to compile those and they are outputted to templates.js. According to the Ember docs when an application loads, it will look for the application template. How does that work with index.html and by changing the file name of the template, is that changing the template's name? Could someone point me in the right direction as to how Ember.js uses precompiled templates? Thanks!

like image 990
Glen Selle Avatar asked Mar 25 '13 03:03

Glen Selle


1 Answers

What I don't understand, is how Ember.js is supposed to use the precompiled templates.

Ember expects that compiled templates will be added to the Ember.TEMPLATES property. When an ember application is loaded it checks for any handlebars script tags and compiles them. Each template is then added to Ember.TEMPLATES using the specified data-template-name attribute as the key. If no data-template-name is provided they key is set to application.

Other than that ember does not care how things get into Ember.TEMPLATES. You can add/remove templates from it manually. For example, https://stackoverflow.com/a/10282231/983357 demonstrates how you can compile a template inline:

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

Now obviously you don't want to write your templates this way, you want grunt to do it for you, but as you can see there is nothing magic going on....

According to the Ember docs when an application loads, it will look for the application template. How does that work with index.html and by changing the file name of the template, is that changing the template's name?

Ember doesn't care about file name of the template, it just cares what string was used as key in Ember.TEMPLATES['key/goes/here']. That said, it makes a lot of sense to use filename as the key for your templates.

Could someone point me in the right direction as to how Ember.js uses precompiled templates?

I think what's missing from your project is probably that the compiled templates are not being added to Ember.TEMPLATES. AFAIK the grunt-contrib-handlebars plugin does not do this. Consider using grunt-ember-templates instead.

like image 171
Mike Grassotti Avatar answered Nov 09 '22 11:11

Mike Grassotti