29

MVC frameworks always allow views to be stored as separate files and retrieved. How is this supposed to be accomplished in Ember.js? I've been looking for hours, so if you want to vote this down as some sort of duplicate, please at least link to a question or resource that provides a definitive, straightforward answer.

For instance, Ember automatically creates an index controller, and automatically renders the index template if you indicate an {{outlet}} as long as the url is /, so I shouldn't need any code other than window.App = Ember.Application.create(); in my app.js for this functionality. How do I create a separate file such as index.handlebars and have Ember find and render it?

Shawn Erquhart
  • 1,820
  • 2
  • 17
  • 30
  • If you are keeping your templates in HTML, create a – xamenrax Feb 09 '13 at 12:11
  • 5
    Thanks Nikita, but the key here is storing templates in separate files. Even a small application will quickly get cumbersome if templates are stored in index.html. I'm really surprised at how many people treat this as some sort of best practice. – Shawn Erquhart Feb 13 '13 at 16:48
  • Anyway, it's not bad to keep all templates in index.html if you are writing a small app. – xamenrax Feb 13 '13 at 19:35
  • Hey, to each his (or her) own :) For anyone reading this, the marked answer probably works, but the more straightforward answer is that Ember just doesn't handle separate views natively. Not yet, anyway. – Shawn Erquhart Feb 14 '13 at 20:23
  • It looks like duplicated to - http://stackoverflow.com/questions/8776151/ember-js-and-requirejs/8806078#8806078 – Wojciech Bednarski Mar 17 '13 at 03:49
  • 4
    erquhart, The standard approach is to use a build tool to compose all of your separate js files into one. Many people in the Ember community use Rails to do this, there are also Node.js based solutions using Grunt which I've linked to in my answer – ianpetzer Apr 17 '13 at 06:36
  • Thank you for also noticing this – Marco Prins Nov 28 '14 at 14:21

6 Answers6

17

In order to preload my templates, I used the following code in my application. It uses jQuery to add the templates to the file and then starts the application. The code could use some tweaking but it's working for me...

var loaderObj = {

    templates : [
    '_personMenu.html',
    'application.html',
    'index.html',
    'people.html',
    'person.html',
    'people/index.html',
    'friend.html'
]
};

loadTemplates(loaderObj.templates);
//This function loads all templates into the view
function loadTemplates(templates) {
    $(templates).each(function() {
        var tempObj = $('<script>');
        tempObj.attr('type', 'text/x-handlebars');
        var dataTemplateName = this.substring(0, this.indexOf('.'));
        tempObj.attr('data-template-name', dataTemplateName);
        $.ajax({
            async: false,
            type: 'GET',
            url: 'js/views/' + this,
            success: function(resp) {
                tempObj.html(resp);
                $('body').append(tempObj);                
            }
        });
    });

}

var App = Ember.Application.create();
//Rest of the code here...
Tom
  • 43,583
  • 4
  • 41
  • 61
Joel Lord
  • 2,175
  • 1
  • 18
  • 25
7

You can use JQuery.ajax to load text file and then Ember.Handlebars.compile to create a template from it:

$.ajax({
   url: 'http://example.com/path/to/your/file',
   dataType: 'text',
   success: function (resp) {
       MyApp.MyView = Ember.View.extend({
           template: Ember.Handlebars.compile(resp),
       });
   }
});
Shimon Rachlenko
  • 5,469
  • 40
  • 51
  • 4
    This is the best suggestion so far, so I'll mark it as the answer. For anyone dealing with this in Ember, this was one of many issues that helped me decide to go back to Angular. It's maddening at times, but it's definitely the more capable framework for CRUD apps. – Shawn Erquhart Feb 13 '13 at 16:51
  • This works great for me... but only if I use `async: true` from @joellord's answer, below. If I do *not* use `async: true`, my templates don't render. – Jonathan Wilson Sep 11 '13 at 19:07
  • What do I do with `MyApp.MyView` after the AJAX has completed? Also the lack of support for this in Ember is astonishing. And no wonder Shawn has gone back to Angular. I'm considering doing the same. – Andrew Gee Jun 17 '14 at 12:15
3

It is definitely the norm to split your JS into multiple files, and then use a build process to stitch them together. Have a look at this answer to another SO Question which includes links for two different techniques to lay your application out based on your choice of server side technology:

EmberJS: Good separation of concerns for Models, Stores, Controllers, Views in a rather complex application?

Community
  • 1
  • 1
ianpetzer
  • 1,828
  • 1
  • 16
  • 21
3

A bit late but I'll add this here for anyone that finds their way here.

Handlebar Template Precompiling is probably your looking for. While normally you end up adding <script type="text/x-handlebars"> tags into the main app file you can also use Handlebars to transpose them into Javascript strings and then store them in Ember.TEMPLATES.

This has a couple of advantages as code is cleaner etc but also you'll be able to use the runtime version of Handlebars which will result in a smaller required runtime library and significant savings from not having to compile the template in the browser.

check out http://handlebarsjs.com/precompilation.html & http://www.smashingmagazine.com/2013/11/07/an-in-depth-introduction-to-ember-js/#what_is_handlebars_template_precompiling for more information.

thisbeme
  • 31
  • 2
0

My solution of this is use server side compile language like Jade (as I'm using ember with nodejs) with Includes feature. You can write each handlebar template as separate files and include them during compilation. Related Jade document: https://github.com/visionmedia/jade#a13

Or you can use Require.js to include other js files, there's a related question.

Community
  • 1
  • 1
inDream
  • 1,277
  • 10
  • 12
  • 1
    I've heard about people using the server side approach - but that really seems to defeat the purpose of using a stable, client side mvc. – Shawn Erquhart Feb 07 '13 at 19:56
0

I'm not sure I'm understanding your question, but if you're asking what I think you're asking, then you'd give your .handlebars document a data-template-name in the script tag: <script ... data-template-name="index">...</script>

Wildhoney
  • 4,969
  • 33
  • 38
  • so if I name it, ember automatically grabs index.handlebars from my root dir - that makes sense, the docs make it seem like the `data-template-name` attribute simply checks for templates that are explicitly defined in the available js files. I haven't tested yet but I'm assuming this works - thanks! – Shawn Erquhart Feb 07 '13 at 17:56
  • No wait, that didn't work. I've now heard five distinct and separate answers to this question between here, various web sources and the #emberjs irc. I also wouldn't want to tie the whole thing down by specifying a data-template-name, since I have script tags wrapping the entire body and would only like to swap in different templates at the `{{outlet}}`. [This is recommended practice in the docs.](http://emberjs.com/guides/application/the-application-template/#toc_the-application-template) – Shawn Erquhart Feb 07 '13 at 19:45
  • Shawn wants to do something like this I think (so do I): `{{partial 'templates/settings.html' action 'users/:id/settings'}}` Is there anything similar to this that works? – Cody Dec 03 '13 at 06:50