Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js + Handlebars each

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. enter image description here

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
}
]
like image 540
netwire Avatar asked Jun 28 '12 20:06

netwire


1 Answers

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.Models 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.

like image 146
mu is too short Avatar answered Oct 19 '22 04:10

mu is too short