Reputation:
I'm trying to create a basic version of this example in CoffeeScript: http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/. All the dependencies are declared as .coffee files in the order I write them (in the body), and jQuery + Underscore + Backbone + Marionette are in the head.
I have a model, thing.coffee
$ ->
console.log 'load model'
class Thing extends Backbone.Model
defaults:
myValue: null
initialize: ->
console.log 'new thing'
window.Thing = Thing
My first hiccup is with scoping: if I don't declare window.Thing
, the next file (the collection of Things
, can't find the model Thing
, and so on. What am I doing wrong there?
I have a collection, things.coffee
$ ->
console.log 'load collection'
class Things extends Backbone.Collection
model: Thing
window.Things = Things
I have a Marionette view, thing_view.coffee
$ ->
console.log 'load composite model view'
ThingView = Backbone.Marionette.ItemView.extend(
template: '#template-thing'
tagName: 'tr'
)
window.ThingView = ThingView
I have a Marionette view, things_view.coffee
$ ->
console.log 'load composite collection view'
ThingsView = Backbone.Marionette.CompositeView.extend(
tagName: 'table'
id: 'things'
template: '#template-things'
itemView: ThingView
appendHtml: (collectionView, itemView) ->
collectionView.$('tbody').append itemView.el
)
window.ThingsView = ThingsView
I have an application myapp.coffee
$ ->
console.log 'load app'
# Load default data
thingsCollection = new Things([
new Thing(myValue: 'uno'),
new Thing(myValue: 'dos')
])
data:
thingsCollection: thingsCollection
# Create application, specify default layouts
MyApp = new Backbone.Marionette.Application()
MyApp.addRegions singleRegion: '#content'
# On application init...
MyApp.addInitializer (data) ->
console.log 'Init application...'
thingsView = new ThingsView(collection: data.thingsCollection)
MyApp.singleRegion.show data.thingsView
# Start application
MyApp.start data
My html file looks like:
<div id="content">
<script type="text/template" id="template-things">
<thead>
<tr class='header'>
<th>myValue</th>
</tr>
</thead>
<tbody>
</tbody>
</script>
<script type="text/template" id="template-thing">
<td><%= myValue %></td>
</script>
</div>
Following the console.log
:
load model
load collection
load composite model view
composite collection view
load app
Init application...
Uncaught TypeError: Cannot call method 'render' of undefined
So, needless to say I'm confused as to what is going on - I'm sure theres tons of things wrong here, so please help!
Upvotes: 2
Views: 5038
Reputation: 434685
if I don't declare
window.Thing
, the next file (the collection ofThings
, can't find the modelThing
, and so on. What am I doing wrong there?
The CoffeeScript compiler wraps each file in a self-executing function so Thing
is local to the wrapper unless you forcibly globalize it by putting it in window
.
I think your real problem is right here:
MyApp.addInitializer (data) ->
console.log 'Init application...'
thingsView = new ThingsView(collection: data.thingsCollection)
MyApp.singleRegion.show data.thingsView
You create a ThingsView
and store it in thingsView
. But then you try to pass data.thingsView
to MyApp.singleRegion.show
but there's nothing in data.thingsView
so you get a complaint when something inside Marionette tries to view.render()
. I think you want this:
thingsView = new ThingsView(collection: data.thingsCollection)
MyApp.singleRegion.show thingsView
or this:
data.thingsView = new ThingsView(collection: data.thingsCollection)
MyApp.singleRegion.show data.thingsView
depending on what this data
object is all about.
Upvotes: 1
Reputation: 6397
The window.Thing
thing is a byproduct of Coffeescript’s global namespace pollution avoidance. The idiomatic way of getting around that is to use an App
namespace.
Initialising your classes only on DOM load is a Backbone anti-pattern. If you namespace your classes, then you just have to ensure you load them in the right order (item view before collection view) and they can be created immediately instead of after the page has loaded.
Can you give us an idea of where the Uncaught TypeError
is happening?
Upvotes: 4