Backbone.js не преминава през колекция

Малко странно...

Имам колекцията:

class Store.Collections.Product extends Backbone.Collection

  url: '/api/products'

  model: Store.Models.Product  

С изглед:

class Store.Views.Origin extends Backbone.View

  initialize: ->
    @collection = new Store.Collections.Product()
    @collection.fetch() 
    @model.bind('change:formatted', @render, this);
    @render()

  events:
    'change [name=origin]': 'setOrigin'

  el: =>
    @options.parent.$('.origin-input')[0]

  template: JST["backbone/templates/shapes/product"]

  render: ->
    $this = $(this.el)
    $this.html(@template(model: @model.toJSON(), errors: @model.errors))
    console.log(@collection)
    @collection.each(@appdenDropdown)
    @delegateEvents()
    this

  appdenDropdown: (product) ->
    console.log("append trigger")
    #view = new Store.Views.Products(model: product)
    #$('#history').append(view.render().el)

с шаблона:

  <div id="history"></div>

Колекцията работи... на

console.log(@collection)

показва данните! въпреки това

@collection.each(@appdenDropdown)

Не прави нищо, не прави грешки или чрез нещо. Просто не прави нищо. Опитвам се да извлека данните от колекцията! Но няма да...


person Charlie Davies    schedule 19.07.2012    source източник
comment
Проверете stackoverflow.com/questions/8413500/ или stackoverflow.com/ въпроси/11459244/   -  person nikoshr    schedule 19.07.2012
comment
btw: защо да правиш $this = ..., когато ИМАШ this.$el. Предлагам да прочетете документацията на backbone.js.   -  person jakee    schedule 19.07.2012
comment
и изчистете отговора на nikoshr: collection.fetch е asynchronous и вие изобразявате своя изглед в метода за инициализация вероятно преди извличането да се върне, така че колекцията е празна. console.log е wtfsynchronous, така че независимо регистрира колекцията като попълнена. Това, което трябва да направите, е да свържете метода за изобразяване към събитието за нулиране на колекцията, за да сте сигурни, че изгледът ще бъде изобразен и след като колекцията бъде попълнена   -  person jakee    schedule 19.07.2012
comment
благодаря, ще погледна, но колекцията не е празна, тъй като показва данните си в console.log, който използвах само за тестване   -  person Charlie Davies    schedule 19.07.2012
comment
console.log, показващ попълнена колекция, е обяснен във втория отговор, който свързах. Резюме: console.log играе трикове, клонирайте колекцията преди влизане и вижте какво получавате   -  person nikoshr    schedule 19.07.2012


Отговори (2)


Това е защото все още няма нищо в колекцията.

@collection.fetch() в инициализатора е асинхронен метод. Трябва да изчакате извличането да завърши, преди да преминете през елементите на колекцията.

Функцията fetch() приема незадължително успешно обратно извикване, което се задейства, когато извличането приключи.

Така че можете да актуализирате кода на инициализатора, за да изчакате, докато колекцията бъде извлечена, преди да извикате render. Ето кода.

initialize: ->
  @collection = new Store.Collections.Product()
  @collection.fetch
    success: =>
      @render()
person Paul    schedule 19.07.2012
comment
можете ли да спрете всичко, докато колекцията се попълни? - person Charlie Davies; 19.07.2012
comment
@CharlieDavies Това побеждава MVC да чака така. Друг начин, по който можете да подходите, е да накарате изгледа да слуша колекцията да се нулира, за да изпълни вашето рендиране. this.collection.on('reset', this.render, this); Така че, когато направите вашето извличане (което задейства събитие „нулиране“), рендирането ще бъде извикано автоматично. - person Brendan Delumpa; 19.07.2012

Проблемът, както други споменаха, е, че fetch е асинхронен, но решението е по-просто: обектът deferred на jQuery:

initialize: ->
  @collection = new Store.Collections.Product()
  @collection.deferred = @collection.fetch()

  @model.bind('change:formatted', @render, this);
  @collection.deferred.done ->
    @render()

Това, което се случва тук е, че когато извикате @collection.deferred.done, вие казвате на jQuery да изчака, докато колекцията се зареди, преди да изпълни render върху нея, което е, което искате. Мисля, че това трябва да работи.

Няколко добри препратки към deferred:

person Chris Salzberg    schedule 19.07.2012
comment
Корекция: Мисля, че отговорът на @Paul, използващ обратното извикване success, всъщност прави същото. - person Chris Salzberg; 20.07.2012
comment
Благодаря ви за помощта, сега това има много повече смисъл за мен! Наистина оценен! - person Charlie Davies; 22.07.2012