简体   繁体   中英

Backbone: view's model is undefined when passing it a model

Here's the entirety of my simple Backbone app. When I instantiate a new view, I'm passing it a model, but when the view calls attributes on the model, it says model is undefined:

class App.Recipe extends Backbone.Model

class App.RecipeList extends Backbone.Collection
  url: '/users/4/recipes'
  model: App.Recipe

@recipeList = new App.RecipeList
@recipeList.fetch()

class App.RecipeView extends Backbone.View
  template: _.template(@model.attributes)
  render: ->
    @$el.html(@template)
    @

@recipeView = new App.RecipeView(model: recipeList.models[0])

$ ->
  $('#featured_recipes').html(window.recipeView.render())

In the console, recipeList.models[0] returns a JSON object that does indeed have an attributes property. So when I instantiate the view and pass it a model, why do I get Uncaught TypeError: Cannot read property 'attributes' of undefined ?

My guess is that @model is getting evaluated at runtime, before I pass in the model. Is there a way to defer that? Or am I wrong?

I've also tried the _.bindAll @ in the initialize function of the view. No dice.

PS — I'm obviously a noob, so if you see other antipatterns or things I'm going to run into here, feel free to mention them.

Edit

I've tried the answer outlined here of adding the template inline in my initialize method like this:

class @App.RecipeView extends Backbone.View
  tagName: 'li'
  initialize: ->
    _.bindAll @, 'render'
    template = _.template $('#featured_recipes').html()
  render: ->
    @$el.html @model.toJSON()
    @

But then I get Cannot call method 'replace' of undefined , which I know is from underscore calling template on something that isn't in the DOM yet, and that's happening because this gets called before my DOM renders. Any thoughts?

Edit 2

Now I've moved the entire app into the footer of my haml layout, so that the $(#featured-_recipes') div is in the DOM. Then I changed the view to this:

class @App.RecipeView extends Backbone.View
  tagName: 'li'
  initialize: ->
    _.bindAll @, 'render'
  @template: _.template $('#featured_recipes').html()
  render: ->
    @$el.html @template(@model.toJSON())
    @

But I'm still getting Cannot call method 'replace' of undefined .

Try the following. I added an initialize method to your View, and I used Backbone's Collection get method to get your recipe.

class App.RecipeView extends Backbone.View
  initialize: (options) ->
    @model = options.recipe 

  template: _.template(@model.attributes)
  render: ->
    @$el.html(@template)
    @


@view = new App.RecipeView
          recipe: recipeList.get(0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM