2011-12-08 3 views
0

警告:コードはCoffeescriptにあります。それが大丈夫だと思う。backbone.jsはコレクションのfetch()に問題があります

私はモデルSong、コレクションSongs、ビューSongsViewです。ここでは、次のとおりです。

SONG_TEMPLATE = ''' 
    <table> 
    {{#if songs.length }} 
    {{#each songs}} 
     <tr><td>{{ this.name }}</td><td>{{ this.duration }}</td></tr> 
    {{/each}} 
    {{/if}} 
    </table> 
''' 

$ -> 
    class Song extends Backbone.Model 
    parse: (response) -> 
     console.log "model parsing #{response}" 
    # 

    class Songs extends Backbone.Collection 
    initialize: -> 
     @model = Song 
     @url = "/songs/data" 

    parse: (response) -> 
     console.log "collection parsing" 
     console.log response 

    # This works. The JSON here was grabbed right out of the XHR response I got from the server and pasted into my code. 

    songs = new Songs(
    [ 
     {"name":"Stray Cat Strut","rating":4,"duration":3}, 
     {"name":"Chinatown","rating":2,"duration":4.2}, 
     {"name":"Sultans of Swing","rating":3,"duration":5.4}, 
     {"name":"Pride & Joy","rating":3,"duration":3} 
    ] 
    ) 

    # This fails. It should be exactly the same as the above code, and indeed, the collection parsing takes place. 
    # However, the view renders nothing. 

    # songs = new Songs 
    # songs.fetch() 

    class SongsView extends Backbone.View 
    initialize: -> 
     @model = Song 
     @render() 

    render: => 
     console.log "render" 
     console.log @collection 
     template = Handlebars.compile(SONG_TEMPLATE) 
     @template = template(songs: @collection.toJSON()) 
     console.log "template: #{@template}" 
     $('#song-list').html @template 

    songView = new SongsView(collection: songs) 

私がいる問題は、JSON文字列からsongsを初期化し、バックボーンはfetch()を使用して、それを移入することができます間には微妙な違いがあるということです。オブジェクトはスクリプトのデバッグウィンドウでは正常に見えますが、喜びはありません。

ここでは何が起こっているのですか?私は正しい方向に向かっていますか?

おかげ

答えて

3

フェッチは非同期メソッドで、これはあなたのビューをレンダリングする際、データが取得されていないが、手動でそれを書くとき、データがあることを意味します。これを行う一般的な方法は、fetchによって呼び出されたリセットトリガーをrenderメソッドにバインドすることです。

class SongsView extends Backbone.View 
    initialize: -> 
    @model = Song 
    @collection.bind("reset", @render) 
    render: => 
    console.log "render" 
    console.log @collection 
    template = Handlebars.compile(SONG_TEMPLATE) 
    @template = template(songs: @collection.toJSON()) 
    console.log "template: #{@template}" 
    $('#song-list').html @template 

さらに、あなたのビューをインスタンシエートする場所の下に、あなたのsongs.fetchをもっと配置する必要があります。

+0

。私がバインドした "フェッチ"イベントはthis.render()をトリガーしません。 @collectionはSongsオブジェクトですが、もちろんイニシャライザでは空です。私は何かが欠けていたのですか?このことが私にはっきりと分かるような参考資料がありますか? (おお!) –

+0

コードを記入してください。公式の文書は私のためにうまくいっています。 http://peepcode.comにもいくつかのスクリーンキャストがあります。http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html – Gazler

+0

でも良いチュートリアルがありますここ:https://gist.github.com/1448858。フェッチをビューの初期化関数に移動しました。それでもrender()は呼び出されません。イベント委譲の問題が発生している可能性があるので、私はdelegateEvents()を試みました。 –

0

Gazlerの回答によれば、問題はfetchが非同期であることです。 Gazlerのソリューションを使用する場合は、コレクションのfetchメソッドがデフォルトでresetイベントをトリガーしなくなることに注意してください。これを解決するための別の解決策は、結果がフェッチされた後のビューを表示するには、jQueryのDeferredの作り方を使用している

my_collection.fetch({reset: true}) 

:したがって、あなたがコレクションを持っている必要がありますが、明示的にresetイベントをトリガ。もっと非同期でデータを取得する際のビューの表示を管理するためのDeferredを使用して1:http://davidsulc.com/blog/2013/04/01/using-jquery-promises-to-render-backbone-views-after-fetching-data/

そして返すために複数の非同期のデータソースを待っている:まだそれが動作するようになっていないhttp://davidsulc.com/blog/2013/04/02/rendering-a-view-after-multiple-async-functions-return-using-promises/

関連する問題