I have an app which uses both Backbone and Handlebars on a server and a client.
Server
Backbone and Express-Handlebars installed
app.js
app.set('views', path.join(__dirname, '/views'));
app.engine('.hbs', expHbs({
defaultLayout: 'index',
extname: '.hbs'
}));
app.set('view engine', '.hbs');
index.js
exports.init = function(req, res){
res.render('contact/index');
};
index.hbs
<div class="row">
<div class="col-sm-6">
<div class="page-header">
<h1>Send A Message</h1>
</div>
<div id="contact"></div>
</div>
....some code
<script id="tmpl-contact" type="text/x-handlebars-template">
<form>
bootstrap with handlebars temlates {{....}} in here
</form>
</script>
Client
On the client I have Backbone and Handlebars installed via Bower
In index.js Backbone.view
var Handlebars = require('handlebars');
app.ContactView = Backbone.View.extend({
el: '#contact',
template: Handlebars.compile( $('#tmpl-contact').html() ),
events: {
'submit form': 'preventSubmit',
'click .btn-contact': 'contact'
},
initialize: function() {
this.model = new app.Contact();
this.listenTo(this.model, 'sync', this.render);
this.render();
},
render: function() {
this.$el.html(this.template( this.model.attributes ));
this.$el.find('[name="name"]').focus();
},
preventSubmit: function(event) {
event.preventDefault();
},
contact: function() {
this.$el.find('.btn-contact').attr('disabled', true);
this.model.save({
name: this.$el.find('[name="name"]').val(),
email: this.$el.find('[name="email"]').val(),
message: this.$el.find('[name="message"]').val()
});
}
});
What happens is that index.hbs renders on the server-side normally, but it is not rendering a form inside script; it shows empty <div id="contact"></div> and doesn't shows any errors in console.
As shown here Using Handlebars with Backbone, a way to replace underscore templating with handlebars is simply to replace _.template with Handlebars.compile, but neither of these options works for me. I also tried different type attributes for <script> and it's still not working.
How can I fix this? Any help is appreciated. Thanks.
Added full index.js on client
/* global app:true */
var Handlebars = require('Нandlebars');
(function() {
'use strict';
app = app || {};
app.Contact = Backbone.Model.extend({
url: '/contact/',
defaults: {
success: false,
errors: [],
errfor: {},
name: '',
email: '',
message: ''
}
});
app.ContactView = Backbone.View.extend({
el: '#contact',
template: Handlebars.compile( $('#tmpl-contact').html() ),
events: {
'submit form': 'preventSubmit',
'click .btn-contact': 'contact'
},
initialize: function() {
this.model = new app.Contact();
this.listenTo(this.model, 'sync', this.render);
this.render();
},
render: function() {
this.$el.html(this.template( this.model.attributes ));
this.$el.find('[name="name"]').focus();
},
preventSubmit: function(event) {
event.preventDefault();
},
contact: function() {
this.$el.find('.btn-contact').attr('disabled', true);
this.model.save({
name: this.$el.find('[name="name"]').val(),
email: this.$el.find('[name="email"]').val(),
message: this.$el.find('[name="message"]').val()
});
}
});
$(document).ready(function() {
app.contactView = new app.ContactView();
});
}());
index.js...? It is not enough to declare a view. You need to initialize it after the required stuff in loaded. - T Jnew app.ContactView()somewhere. BTW if you're sharing code blocks please edit and add it in question. They are unreadable in comments - T J$(document).ready(function() { app.contactView = new app.ContactView(); });will initialize the view then your app loads. Is the content ofindex.hbsavailable at that point? or is it loaded later? - T J