I’ve been banging my head against the wall trying to learn Backbone.js. My usual process for learning a new technology or framework is to try to do things the ugliest way possible to get it working, and then refactor and spot patterns to organize things. One of the most frustrating pieces of my stack right now are my handlebars templates, which started out lumped into a bunch of <script> tags at the top of my page.
For those of you that have tried working with Handlebars before, you’re probably more than familiar with blocks of {{code}} like this stuck into your <head> tag:
// Report - Sales Tax
script(type='text/x-handlebars-template', id='salesTax-template')
h1 Sales Tax
{{#each report}}
{{#dates}}
h3 Start Date:
{{start}}
| End Date:
{{end}}
{{/dates}}
{{#totals}}
h2 Totals:
p Services:
{{services}}
p Products:
{{products}}
{{/totals}}
h2 Tax:
{{#tax}}
p Services:
{{services}}
p Products:
{{products}}
{{/tax}}
{{/each}}
I was really frustrated with these files cluttering up my layout.jade file in my root directory, because I need to deliver the templates when I first load the Backbone app. I’ve read a ton about how to split Handlebars templates into their own files using Backbone, but haven’t seen any decent solutions, so I set out to solve it using other tools in my stack.
The (ridiculously simple) solution I came up with was to use Jade partials on my NodeJS server so that with the initial pageload, Jade would compile all of the templates into one main HTML file and serve it to the client! Easy.
So here’s the code I’ve got in my layout.jade:
// Handlebars Templates - move these to separate files eventually
!=partial('templates/reports')
!=partial('templates/reports/salesTax')
!=partial('templates/reports/newClients')
!=partial('templates/reports/selectStylist')
The !=partial command searches the views directory for any files matching the path/filename you specify ending in .jade. For example, I’ve used the folder ./templates and placed all of the templates for my reports under ./templates/reports. The base template that acts as a container for my other report templates is called index.jade and is called on the first line. The rest of the templates are for individual report templates.
Finally, I’ve included the following code in my initialize() function for each of my Views to render the templates.
reportView.coffee:
### Reports - Base collection for all reports ###
class window.Reports extends Backbone.Collection
model: Report
# Overall report master view!
class window.ReportView extends Backbone.View
initialize: ->
@el = $('.containerOuter')
_.bindAll this, 'render'
# Compile Handlebars template at init
# (Not sure if we have to do this each time or not)
source = $('#report-template').html()
@template = Handlebars.compile source
@render()
render: ->
renderedContent = @template { }
$(@el).html renderedContent
