2012-03-06 15 views
6

backbone.js Collectionの真ん中に新しいモデルアイテムを挿入し、新しいアイテムを正しい位置に含めるようにコレクションのViewを更新する簡単な方法はありますか?backbone.jsコレクションにアイテムを挿入する

私は、リストからアイテムを追加/削除するためのコントロールを行っています。各リストアイテムにはそれぞれModelViewがあり、コレクション全体にはViewもあります。

各アイテムビューには、アイテムのモデルをクローン化し、クリックされたアイテムの下のインデックス位置のコレクションに挿入するDuplicateボタンがあります。

アイテムをコレクションに挿入するのは簡単でしたが、コレクションビューを更新する方法がわかりません。

ListView = Backbone.View.extend({ 
    el: '#list-rows', 
    initialize: function() { 
     _.bindAll(this); 
     this.collection = new Items(); 
     this.collection.bind('add', this.addItem); 
     this.render(); 
    }, 
    render: function() { 
     this.collection.each(this.addItems); 
     return this; 
    }, 
    addItem: function (item) { 
     var itemView = new ItemView({ model: item }), 
      rendered = itemView.render().el, 
      index = this.collection.indexOf(item), 
      rows = $('.item-row'); 

     if (rows.length > 1) { 
     $(rows[index - 1]).after(rendered); 
     } else { 
     this.$el.append(rendered); 
     } 
    } 
} 

この実装は、作業の一種であるが、私は新しい項目を追加するとき、私は奇妙なバグを取得しています:私はこのような何かをしようとしてきました。私はそれらを並べ替えることができると確信していますが、...

私の頭の中には、これを行うためのよりよい方法があることを伝え続けています。手動でどこに新しいItemViewを挿入するのか把握しているのは本当にうんざりしているようです。コレクションビューでコレクションを再レンダリングする方法は分かりませんでしたか?

提案がありますか?

答えて

4

普通のやり方は、ListViewは、それぞれrenderの機能にItemViewをレンダリングさせます。

ListView = Backbone.View.extend({ 
    el: '#list-rows' 
    , initialize: function() { 
    _.bindAll(this); 
    this.collection = new Items(); 
    this.collection.bind('add', this.render); 
    this.render(); 
    } 
    , render: function() { 
    this.$el.empty(); 
    var self = this; 
    this.collection.each(function(item) { 
     self.$el.append(new ItemView({ model: item }).render().el); 
    }); 
    return this; 
    } 
} 

あなたがthis.collection.add(someModel, {at: index})を呼び出す毎回、ビューがそれに応じて再レンダリングされます。その後、私はちょうどこのように、render関数にaddイベントをバインドします。

+0

これを動作させるには、 'render'メソッドの中で'(.item-row).remove() 'の呼び出しを追加する必要がありましたが、それは良い解決策です。 (さもなければ、再レンダリングされたアイテムは、既存のレンダリングされたアイテムの最後に追加されていました。)助けてくれてありがとう! –

+0

ああ、 '$ el.empty()'を実行してコレクションをループする前に '$ el'をクリアすることができます:) – sntran

+0

これは、現在コレクションにアイテムを追加する方法です。新しいアイテムをコレクションの正しい場所に置いています。私は上記のコメントに2つのタイプミスがあることに気付きました。最後にコレクションがレンダリングされたときに作成されたアイテムを削除するには '$( '。item-row')。remove()を呼び出します。表示をリセットするだけです。それを考えると、私がしたいことをするかもしれない 'リセット'メソッドがあります。私はそれを呼び出して、 'render'を呼び出してみます。 –

9

新しい要素を追加するときにコレクション全体を再レンダリングするのは最適な解決策ではないと思います。新しいアイテムを適切な場所に挿入するよりも、特にリストが長い場合は時間がかかります。

また、以下のシナリオを考えます。あなたのコレクションにいくつかのアイテムをロードし、次にn個のアイテムを追加します(ユーザーが「もっと読み込み」ボタンをクリックすると)。これを行うには、をオプションの1つとして渡すfetch()メソッドを呼び出します。データがサーバーから返されると、 'add'イベントがn回実行され、リストの再レンダリングが終了しますn回。

私は実際にここに私のコールバックは、「追加」イベントにだ、あなたの質問に、コードのバリアントを使用しています:

var view, prev, prev_index; 
view = new ItemView({ model: new_item }).render().el; 
prev_index = self.model.indexOf(new_item) - 1; 
prev = self.$el.find('li:eq(' + prev_index + ')'); 
if (prev.length > 0) { 
    prev.after(view); 
} else { 
    self.$el.prepend(view); 
} 

だから、基本的に私はちょうど:eq() jQueryのセレクタを使用しての代わりに取得していますあなたがしているすべての要素は、より少ないメモリを使用する必要があります。

+0

これはうまくいきますが、リストの各項目の横に数字が表示されているので、数値を同期させるために再レンダリングする必要があります。その周りを見ることができません。バマー。私はここでシンプルさが好きです。 – byron

関連する問題