Selective Build Backbone + Rails
Previously, my Backbone router looked like this:
class App.Routers.ThingsRouter extends Backbone.Router
routes: '': 'index'
routes: 'previews/:id': 'show'
initialize: ->
@collection = new App.Collections.ThingsCollection
@collection.fetch
index: ->
view = new App.Views.ThingsIndex(collection: @collection)
$('#app-container').html(view.render().el)
show: (id) ->
@model = @collection.get(id)
view = new App.Views.ThingsShow(model: @model)
$('#app-container').html(view.render().el)
On going to http://localhost
I get the render index
, and on clicking on the individual items I get the render show
. However, if I just went to http://localhost/things/1
(i.e. typing in the url) the view show
won't show. I figured this was happening because the submission was done before completion @collection.fetch
. I changed my router to the following:
class App.Routers.ThingsRouter extends Backbone.Router
routes: '': 'index'
routes: 'previews/:id': 'show'
initialize: ->
@collection = new App.Collections.ThingsCollection
index: ->
@collection.fetch success: =>
view = new App.Views.ThingsIndex(collection: @collection)
$('#app-container').html(view.render().el)
show: (id) ->
@collection.fetch success: =>
that.model = that.collection.get(id)
view = new App.Views.ThingsShow(model: @model)
$('#app-container').html(view.render().el)
Which works great. However, there is obviously a slight delay as the collection is reordered every time the routes are switched. Is this a good baseline? Not sure if there is a better way to do this.
source to share
This is a great use case for jQuery's Deferred () method .
Just create a Deferred object and attach it to the router. Then select the collection in the initialization method and call the resolve()
Deferred object. Your indexing and displaying methods can subscribe to the callback done
and instantiate the view. This callback will not run until the collection is received. And if it has already been extracted, it starts immediately.
class App.Routers.ThingsRouter extends Backbone.Router
routes: '': 'index'
routes: 'previews/:id': 'show'
initialize: ->
@collectionFetched = new $.Deferred
@collection = new App.Collections.ThingsCollection
@collection.fetch success: ->
@collectionFetched.resolve()
index: ->
that = this
@collectionFetched.done ->
view = new App.Views.ThingsIndex(collection: that.collection)
$('#app-container').html(view.render().el)
show: (id) ->
that = this
@collectionFetched.done ->
that.model = that.collection.get(id)
view = new App.Views.ThingsShow(model: that.model)
$('#app-container').html(view.render().el)
source to share