Reputation: 163
I am new to ember.js. I managed to pre-compile templates using a Grunt file. However, when I include them in an index.html, I see an empty page, templates are not rendered. What am I doing wrong? If I don't compile templates and include directly in index.html it works.
I installed everything using yeoman.io (using bower packages grunt-ember-templates, ember, webapp scaffolding)
My index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>My New App</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/handlebars/handlebars.js"></script>
<script src="bower_components/ember/ember.js"></script>
<script src="scripts/templates.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
My App.js:
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
Templates:
Edit: application.hbs
<h2>Welcome to Ember.js</h2>
{{outlet}}
Edit: index.hbs
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
Compiled templates in templates.js:
define(["ember"], function(Ember){
Ember.TEMPLATES["application"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
var buffer = '', stack1;
data.buffer.push("<h2>Welcome to Ember.js</h2>\n\n");
stack1 = helpers._triageMustache.call(depth0, "outlet", {hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:["ID"],data:data});
if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
return buffer;
});
Ember.TEMPLATES["index"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
var buffer = '', stack1, self=this;
function program1(depth0,data) {
var buffer = '', stack1;
data.buffer.push("\n <li>");
stack1 = helpers._triageMustache.call(depth0, "item", {hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:["ID"],data:data});
if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
data.buffer.push("</li>\n ");
return buffer;
}
data.buffer.push("\n<ul>\n ");
stack1 = helpers.each.call(depth0, "item", "in", "model", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0,depth0,depth0],types:["ID","ID","ID"],data:data});
if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
data.buffer.push("\n</ul>\n");
return buffer;
});
});
Upvotes: 0
Views: 1806
Reputation: 163
I solved the problem by removing amd:true option from grunt-ember-templates grunt configuration. To be honest I had added it without knowing what it does.
For completeness, here is my current grunt file. This file is autogenerated by yeoman.io webapp generator, and I have only added a grunt-ember-templates configuration to it (ones defined under emberTemplates).
As of today, all guides I found online were incomplete or out of date, and this worked for me.
// Generated on 2014-03-24 using generator-webapp 0.4.8
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
grunt.loadNpmTasks('grunt-ember-templates');
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
config: {
// Configurable paths
app: 'app',
dist: 'dist'
},
emberTemplates: {
compile: {
options: {
templateBasePath: /app\/templates\//
//templateName: function(sourceFile) {
// console.log(sourceFile.replace(/app\/templates\//, ''));
// return sourceFile.replace(/app\/templates\//, '');
// }
},
files: {
'<%= config.app %>/scripts/templates.js': ['<%= config.app %>/templates/*.hbs']
}
}
},
// Watches files for changes and runs tasks based on the changed files
watch: {
emberTemplates: {
files: '<%= config.app %>/templates/*.hbs',
tasks: ['emberTemplates', 'livereload']
},
bower: {
files: ['bower.json'],
tasks: ['bowerInstall']
},
js: {
files: ['<%= config.app %>/scripts/{,*/}*.js'],
tasks: ['jshint'],
options: {
livereload: true
}
},
jstest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['test:watch']
},
gruntfile: {
files: ['Gruntfile.js']
},
styles: {
files: ['<%= config.app %>/styles/{,*/}*.css'],
tasks: ['newer:copy:styles', 'autoprefixer']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= config.app %>/{,*/}*.html',
'.tmp/styles/{,*/}*.css',
'<%= config.app %>/images/{,*/}*'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
livereload: 35729,
// Change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= config.app %>'
]
}
},
test: {
options: {
port: 9001,
base: [
'.tmp',
'test',
'<%= config.app %>'
]
}
},
dist: {
options: {
open: true,
base: '<%= config.dist %>',
livereload: false
}
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= config.dist %>/*',
'!<%= config.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: [
'Gruntfile.js',
'<%= config.app %>/scripts/{,*/}*.js',
'!<%= config.app %>/scripts/vendor/*',
'test/spec/{,*/}*.js'
]
},
// Mocha testing framework configuration options
mocha: {
all: {
options: {
run: true,
urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
}
}
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the HTML file
bowerInstall: {
app: {
src: ['<%= config.app %>/index.html'],
ignorePath: '<%= config.app %>/'
}
},
// Renames files for browser caching purposes
rev: {
dist: {
files: {
src: [
'<%= config.dist %>/scripts/{,*/}*.js',
'<%= config.dist %>/styles/{,*/}*.css',
'<%= config.dist %>/images/{,*/}*.*',
'<%= config.dist %>/styles/fonts/{,*/}*.*',
'<%= config.dist %>/*.{ico,png}'
]
}
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
options: {
dest: '<%= config.dist %>'
},
html: '<%= config.app %>/index.html'
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
options: {
assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
},
html: ['<%= config.dist %>/{,*/}*.html'],
css: ['<%= config.dist %>/styles/{,*/}*.css']
},
// The following *-min tasks produce minified files in the dist folder
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/}*.{gif,jpeg,jpg,png}',
dest: '<%= config.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/}*.svg',
dest: '<%= config.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeCommentsFromCDATA: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
useShortDoctype: true
},
files: [{
expand: true,
cwd: '<%= config.dist %>',
src: '{,*/}*.html',
dest: '<%= config.dist %>'
}]
}
},
// By default, your `index.html`'s <!-- Usemin block --> will take care of
// minification. These next options are pre-configured if you do not wish
// to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= config.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css',
// '<%= config.app %>/styles/{,*/}*.css'
// ]
// }
// }
// },
// uglify: {
// dist: {
// files: {
// '<%= config.dist %>/scripts/scripts.js': [
// '<%= config.dist %>/scripts/scripts.js'
// ]
// }
// }
// },
// concat: {
// dist: {}
// },
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= config.app %>',
dest: '<%= config.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'images/{,*/}*.webp',
'{,*/}*.html',
'styles/fonts/{,*/}*.*'
]
}]
},
styles: {
expand: true,
dot: true,
cwd: '<%= config.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
// Run some tasks in parallel to speed up build process
concurrent: {
server: [
'copy:styles'
],
test: [
'copy:styles'
],
dist: [
'copy:styles',
'imagemin',
'svgmin'
]
}
});
grunt.registerTask('serve', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'concurrent:server',
'autoprefixer',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('server', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run([target ? ('serve:' + target) : 'serve']);
});
grunt.registerTask('test', function (target) {
if (target !== 'watch') {
grunt.task.run([
'clean:server',
'concurrent:test',
'autoprefixer'
]);
}
grunt.task.run([
'connect:test',
'mocha'
]);
});
grunt.registerTask('build', [
'clean:dist',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'concat',
'cssmin',
'uglify',
'copy:dist',
'rev',
'usemin',
'htmlmin'
]);
grunt.registerTask('default', [
'newer:jshint',
'test',
'build'
]);
};
Upvotes: 0
Reputation: 1903
You're not specific about how you are compiling your templates. Are they from *.hbs files, or are you using a different approach ?
It seems to me, that you are attempting to compile your templates.html file as a single template, as it has this code in the template itself:
data.buffer.push("\n<script type=\"text/x-handlebars\">\n
Each of your template files should only contain the contents of the template, and not the script tag itself.
Normally, you will put each .hbs file in a separate file that together with the used to determine the name of the template.
I did a presentation earlier, where I am live coding an application using grunt. This screencast do show how you can organize your .hbs files, while the source code shows how they are complied. This shows how my development process is, and it goes through building a complete app with grunt as the build system.
The presentation is up on YouTube: https://www.youtube.com/watch?v=KH5RreHtaaQ The source code is on GitHub: https://github.com/joachimhs/WarmCroc-Ember
Hope that helps!
Upvotes: 1