Reputation: 183
I am trying to access items of an array in a model and it's raising errors but seems to be finding the correct attribute and writing it to the console still
class GD.Views.Place extends Backbone.View
template: JST['mobile/templates/place']
initialize: ->
@model.on('change', @render, this)
render: ->
$(@el).html(@template(place:@model, open:@openNow() ))
console.log @model.get("coordinates")
console.log @model.get("coordinates")[0]
console.log @model.get("coordinates")[1]
console.log("done")
this
openNow: ->
...
The view is not rendering on-screen and I am seeing this message in my console
Uncaught TypeError: Cannot read property '0' of undefined
GD.Views.Place.Place.render
GD.Routers.Main.Main.place
_.extend.route
(anonymous function)
_.some._.any
_.extend.loadUrl
_.extend.start
window.GD.init
(anonymous function)
jQuery.Callbacks.fire
jQuery.Callbacks.self.fireWith
jQuery.extend.ready
DOMContentLoaded
[51.4528837, -0.9739059999999428]
51.4528837
-0.9739059999999428
done
The error message is referring to the 2nd and 3rd console.log lines above. It also seems to be raising errors when accessing further attributes in embedded hashes.
I don't understand why this is happening or how to work around it. Thanks for the help/patience in advance!
Upvotes: 1
Views: 1135
Reputation: 434985
The usual pattern with a Backbone view is this:
v = new V
$(something).append(v.render().el)
If you combine that with a common pattern for initializing a model:
m = new M
m.fetch() # asynchronous!
then you can get this:
m = new M
m.fetch()
v = new V(model: m)
$(something).append(v.render().el)
That would allow the v.render()
inside the append
call to happen before the model has been fetched from the server. In your case, that would mean that @model.get('coordinates')
would be undefined
in the v.render()
call above and you would get:
Uncaught TypeError: Cannot read property '0' of undefined
...
then, the m.fetch()
gets its data from the server and triggers a "change"
event, that event would then call render
on your view and you would get this:
[51.4528837, -0.9739059999999428]
51.4528837
-0.9739059999999428
done
That sequence of messages is exactly what you're seeing in your console.
I'd guess that you'r doing something like this (as above):
m = new M
m.fetch()
v = new V(model: m)
$(something).append(v.render().el)
Try checking to see if @model
is actually loaded inside render
and throw up some sort of "loading..." message if it isn't; then let the "change"
event trigger the "real" rendering.
PS: You can use @
instead of this
in CoffeeScript:
initialize: ->
@model.on('change', @render, @)
render: ->
#...
@
You could also use a fat arrow (=>
) to define your render
method and not worry about supply a context to @model.on
:
initialize: ->
@model.on('change', @render)
render: =>
#...
@
Furthermore, if you're using a recent version of Backbone, you have a $el
in your view instances so you could:
render: =>
@$el.html(...)
#...
@
Upvotes: 4