I'm trying to convert Ryan's RailsCast on Backbone.js to work with Handlebars and am stuck on a simple problem.
I can't seem to be able to iterate through a JSON array and display the result. I'm using these gems in my Gemfile
gem 'backbone-on-rails'
gem 'handlebars_assets'
In my index.jst.hbs
, I have the following:
{{entries.length}}
<ul>
{{#each entries.models}}
<li>{{name}}</li>
{{/each}}
</ul>
The API call seems to be working, as you can see in the count of 7 in the screenshot.
However, the content of each model isn't being displayed. Here's the View (index.js.coffee) and JSON response below.
class Raffler.Views.EntriesIndex extends Backbone.View
template: JST['entries/index']
initialize: ->
#triggered when view gets created, listen to 'reset' event, then re-@render, pass 'this' for context binding
@collection.on('reset', @render, this)
render: ->
$(@el).html(@template(entries: @collection))
this
JSON:
[
{
"created_at":"2012-06-28T18:54:28Z",
"id":1,
"name":"Matz",
"updated_at":"2012-06-28T18:54:28Z",
"winner":null
},
{
"created_at":"2012-06-28T18:54:28Z",
"id":2,
"name":"Yehuda Katz",
"updated_at":"2012-06-28T18:54:28Z",
"winner":null
},
{
"created_at":"2012-06-28T18:54:28Z",
"id":3,
"name":"DHH",
"updated_at":"2012-06-28T18:54:28Z",
"winner":null
},
{
"created_at":"2012-06-28T18:54:28Z",
"id":4,
"name":"Jose Valim",
"updated_at":"2012-06-28T18:54:28Z",
"winner":null
},
{
"created_at":"2012-06-28T18:54:29Z",
"id":5,
"name":"Dr Nic",
"updated_at":"2012-06-28T18:54:29Z",
"winner":null
},
{
"created_at":"2012-06-28T18:54:29Z",
"id":6,
"name":"John Nunemaker",
"updated_at":"2012-06-28T18:54:29Z",
"winner":null
},
{
"created_at":"2012-06-28T18:54:29Z",
"id":7,
"name":"Aaron Patterson",
"updated_at":"2012-06-28T18:54:29Z",
"winner":null
}
]
Your @collection
is, presumably, a Backbone.Collection
. Handlebars will see it as an array of some sort so {{entries.length}}
works as expected and {{#each entries.models}}
iterates the right number of times; however, Handlebars has no idea what to do with the Backbone.Model
s that are inside @collection.models
.
Convert the @collection
to raw data using toJSON
, Handlebars knows what to do with simple JavaScript arrays and objects:
render: ->
@$el.html(@template(entries: @collection.toJSON()))
@
And then adjust your template to look at just entries
rather than entries.models
:
<ul>
{{#each entries}}
<li>{{name}}</li>
{{/each}}
</ul>
Demo: http://jsfiddle.net/ambiguous/tKna3/
A general rule with Backbone is to pass model.toJSON()
or collection.toJSON()
to your templates so that they don't have to know about Backbone methods (such as get
) and so that your templates don't accidentally alter your models and collections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With