dxu
dxu

Reputation: 459

Backbone.js with Rails, @collection is 'undefined'?

I'm brand new to Backbone.js, and I'm trying to integrate it into my current rails app. I'm following the tutorials from railscasts, but I'm having trouble with integrating them. Basically, I'm at the point where I'm trying to call my resource (projects), and just display them on the page. My router looks as follows:

class Placeholder.Routers.Projects extends Backbone.Router
  routes:
    '': 'index'
    'projects/:id':'show'

  initialize: ->
    @collection = new CIS196Project.Collections.Projects()
    @collection.fetch()

  index: ->
    view = new Placeholder.Views.ProjectsIndex()
    $('#container').html(view.render().el)

  show: (id) ->
    alert "Project #{id}"

and my view looks like:

class Placeholder.Views.ProjectsIndex extends Backbone.View

  template: JST['projects/index']

  initialize: ->
    document.write(@collection)
    @collection.on('reset', @render, this)

  render: ->
    $(@el).html(@template(projects: @collection))
    this

all of which I mostly took straight from the tutorial. I added the document.write(@collection) to test.

Upon loading the page, I get the error:

projects_index.js:17 Uncaught TypeError: Cannot call method 'on' of undefined

I'm successfully making the fetch() in the router, because in my logs, the GET request successfully passes through, and on trying it in chrome's console, the fetch should return an array of size 1, but instead, it gives that error, and then loads the default rails view from its controller (I'm also not sure why this occurs. I have a template that is defined, and yet right when it throws this error, it just reverts back to the previous, unless I call document.write). Upon calling document.write, @collection comes out as 'undefined'.

Thanks for any help any of you could give!

Upvotes: 1

Views: 506

Answers (1)

mu is too short
mu is too short

Reputation: 434615

You are creating your collection as an instance variable in your router:

class Placeholder.Routers.Projects extends Backbone.Router
  #...
  initialize: ->
    @collection = new CIS196Project.Collections.Projects()
    #...

but you never give that collection to your view:

index: ->
  view = new Placeholder.Views.ProjectsIndex()
  #... 

If you supply the collection to your view:

index: ->
  view = new Placeholder.Views.ProjectsIndex(collection: @collection)
  #...

then you'll have a collection instance variable in your view.

From the fine manual:

constructor / initialize new View([options])

[...] There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName and attributes.

So just specifying the collection option when you instantiate the view is sufficient to get a @collection in the view.

As an aside, console.log(@collection) is a better idea than document.write(@collection), document.write has unfortunate side effects (like sometimes erasing the whole page) and console.log will produce more readable output.

Upvotes: 2

Related Questions