Nick Sergeant
Nick Sergeant

Reputation: 38163

Representing existing HTML as Backbone.js data structures in CoffeeScript

I'm having a rough time wrapping my head around this.

I have an HTML list, and I want to use Backbone.js to handle events on those list items. Here's what I've got so far. This is a simplified scenario to help me better understand how to structure a larger application. For my example, I simply want to ingest an existing HTML list into the Backbone structure, and handle click events through the Backbone view.

I'm getting an error related to using @model in the view, but I'm fairly certain I'm misunderstanding things conceptually here.

CoffeeScript:

$ ->
    class Item extends Backbone.Model
        name: null

    class ItemList extends Backbone.Collection
        model: Item

    class ItemView extends Backbone.View
        tagName: 'li'

        initialize: =>
            @model.bind('change', this.render)
            @model.view = this

        events:
            'click' : 'clicked'

        clicked: -> 
            console.log 'clicked'

        render: =>
            this

    class ItemListView extends Backbone.View
        el: $('ul#test')

        initialize: =>
            $('li', @el).each(@addItem)

        addItem: (item) ->
            item = new ItemView({ el: item })

        render: =>
            this

    Items = new ItemListView

HTML:

<ul id="test">
    <li>Hi thar</li>
    <li>Yeah</li>
    <li>OK</li>
</ul>

Here's a jsfiddle I started earlier: http://jsfiddle.net/Saxx4/

Upvotes: 0

Views: 441

Answers (1)

nrabinowitz
nrabinowitz

Reputation: 55678

I never really like CoffeeScript (Javascript is so nice, why replace it?), but it looks like there are a few issues here:

  • You're getting an error on @model because you never set it on the ItemView. This doesn't happen automatically - you have to either instantiate the view's model in initialize() or pass it into the constructor, e.g.:

    addItem: (item) ->
        model = new ItemView({ 
            el: item, 
            model: new Item({ 
                // assuming you might want the list item text
                // in the model data
                text: $(item).text() 
            }) 
        })
    
  • You usually just want to specify a selector in el, not a jQuery object - otherwise the DOM might not be ready when you load your Backbone code: el: '#test'

  • You need to pass an options object to the ItemListView constructor, not just a single argument, no matter what you do in initialize():

    class ItemListView extends Backbone.View
    
        initialize: (opts) =>
            opts.items.each(@addItem)
    
        // ...
    
    Items = new ItemListView({ items: $('ul#test li') })
    

Upvotes: 2

Related Questions