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
Кстати: зачем $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