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.

+3


source to share


1 answer


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)

      

+6


source







All Articles