2011-12-13 10 views
4

私はBackbone.js(私の最初のバックボーンを使ったアプリケーション)でテストアプリケーションを構築しています。アプリはこのように書きます:計画のBackbone.jsコレクションにモデルを追加する問題

  1. ロードサーバ「計画」からのデータ
  2. ビルドの一覧と画面
  3. に見せる新しい計画が追加される新しい計画
  4. を追加するためのボタンがあります(追加したばかりの計画が含ま)

私の問題私を、コレクションに追加

  • は、インデックスページにリダイレクト(今のように、サーバーに保存していない)と新しいコレクションを表示プランを保存するときに、モデルをコレクションに追加して、最初のビューにリダイレクトします。この時点で、私はサーバーからデータを取得します。サーバーからデータを取得すると、コレクションが上書きされ、追加されたモデルはなくなりました。

    これを防ぐにはどうすればよいですか?私はこれを行う方法を見つけましたが、まったく正しい方法ではありません。下に私のコード例があります。助けてくれてありがとう。

    PlansListViewビュー:

    var PlansListView = Backbone.View.extend({ 
    
        tagName : 'ul', 
    
        initialize : function() 
        { 
         _.bindAll(this, 'render', 'close'); 
         //reset the view if the collection is reset 
         this.collection.bind('reset', this.render , this); 
    
        }, 
        render : function() 
        { 
         _.each(this.collection.models, function(plan){ 
    
          $(this.el).append(new PlansListItemView({ model: plan }).render().el); 
    
         }, this); 
    
         return this; 
        }, 
        close : function() 
        { 
         $(this.el).unbind(); 
         $(this.el).remove(); 
    
        } 
    });//end 
    

    NewPlanView保存方法

    var NewPlanView = Backbone.View.extend({ 
    
        tagName : 'section', 
        template : _.template($('#plan-form-template').html()), 
        events : { 
         'click button.save' : 'savePlan', 
         'click button.cancel' : 'cancel' 
    
        }, 
        intialize: function() 
        { 
         _.bindAll(this, 'render', 'save', 'cancel'); 
    
        }, 
        render : function() 
        { 
         $('#container').append($(this.el).html(this.template(this.model.toJSON())));          
         return this; 
        }, 
        savePlan : function(event) 
        { 
    
         this.model.set({ 
    
          name : 'bad plan', 
          date : 'friday', 
          desc : 'blah', 
          id : Math.floor(Math.random()*11), 
          total_stops : '2'   
         }); 
    
         this.collection.add(this.model); 
    
         app.navigate('', true); 
         event.preventDefault(); 
    
        }, 
        cancel : function(){} 
    }); 
    

    ルーター(デフォルトの方法):

    index : function() 
        { 
         this.container.empty(); 
         var self = this; 
    
         //This is a hack to get this to work 
         //on default page load fetch all plans from the server 
         //if the page has loaded (this.plans is defined) set the updated plans collection to the view 
         //There has to be a better way!! 
         if(! this.plans) 
         { 
          this.plans = new Plans(); 
    
    
          this.plans.fetch({ 
    
           success: function() 
           { 
            self.plansListView = new PlansListView({ collection : self.plans }); 
            $('#container').append(self.plansListView.render().el); 
            if(self.requestedID) self.planDetails(self.requestedID); 
           } 
          }); 
         } 
         else 
         { 
          this.plansListView = new PlansListView({ collection : this.plans }); 
          $('#container').append(self.plansListView.render().el); 
          if(this.requestedID) self.planDetails(this.requestedID); 
    
         } 
        }, 
    

    新プランルート:

    newPlan : function() 
        { var plan = new Plan({name: 'Cool Plan', date: 'Monday', desc: 'This is a great app'}); 
         this.newPlan = new NewPlanView({ model : plan, collection: this.plans }); 
         this.newPlan.render(); 
        } 
    

    FULL CODE (関数($){

    var Plan = Backbone.Model.extend({ 
    
        defaults: { 
         name : '', 
         date : '', 
         desc : '' 
        } 
    }); 
    
    var Plans = Backbone.Collection.extend({ 
    
        model : Plan, 
        url : '/data/' 
    
    });  
    
    
    
    
    
    
    $(document).ready(function(e){ 
    
        var PlansListView = Backbone.View.extend({ 
    
         tagName : 'ul', 
    
         initialize : function() 
         { 
          _.bindAll(this, 'render', 'close'); 
          //reset the view if the collection is reset 
          this.collection.bind('reset', this.render , this); 
    
         }, 
         render : function() 
         { 
          _.each(this.collection.models, function(plan){ 
    
           $(this.el).append(new PlansListItemView({ model: plan }).render().el); 
    
          }, this); 
    
          return this; 
         }, 
         close : function() 
         { 
          $(this.el).unbind(); 
          $(this.el).remove(); 
    
         } 
        });//end 
    
        var PlansListItemView = Backbone.View.extend({ 
    
         tagName : 'li', 
         template : _.template($('#list-item-template').html()), 
         events :{ 
    
          'click a' : 'listInfo' 
         }, 
         render : function() 
         { 
          $(this.el).html(this.template(this.model.toJSON())); 
          return this;    
         }, 
         listInfo : function(event) 
         { 
    
    
         } 
    
        });//end 
    
    
        var PlanView = Backbone.View.extend({ 
    
         tagName : 'section', 
         events : { 
          'click button.add-plan' : 'newPlan' 
         }, 
         template: _.template($('#plan-template').html()), 
         initialize: function() 
         { 
          _.bindAll(this, 'render', 'close', 'newPlan');    
         }, 
         render : function() 
         { 
          $('#container').append($(this.el).html(this.template(this.model.toJSON()))); 
          return this; 
         }, 
         newPlan : function(event) 
         { 
          app.navigate('newplan', true); 
         }, 
         close : function() 
         { 
          $(this.el).unbind(); 
          $(this.el).remove(); 
         } 
    
        });//end 
    
    
        var NewPlanView = Backbone.View.extend({ 
    
         tagName : 'section', 
         template : _.template($('#plan-form-template').html()), 
         events : { 
          'click button.save' : 'savePlan', 
          'click button.cancel' : 'cancel' 
    
         }, 
         intialize: function() 
         { 
          _.bindAll(this, 'render', 'save', 'cancel'); 
    
         }, 
         render : function() 
         { 
          $('#container').append($(this.el).html(this.template(this.model.toJSON())));          
          return this; 
         }, 
         savePlan : function(event) 
         { 
    
          this.model.set({ 
    
           name : 'bad plan', 
           date : 'friday', 
           desc : 'blah', 
           id : Math.floor(Math.random()*11), 
           total_stops : '2'   
          }); 
    
          this.collection.add(this.model); 
    
          app.navigate('', true); 
          event.preventDefault(); 
    
         }, 
         cancel : function(){} 
        }); 
    
    
    
        var AppRouter = Backbone.Router.extend({ 
    
         container : $('#container'), 
    
         routes : { 
    
          ''    : 'index', 
          'viewplan/:id' : 'planDetails', 
          'newplan'   : 'newPlan' 
         }, 
         initialize: function(){ 
    
         }, 
         index : function() 
         { 
          this.container.empty(); 
          var self = this; 
    
          //This is a hack to get this to work 
          //on default page load fetch all plans from the server 
          //if the page has loaded (this.plans is defined) set the updated plans collection to the view 
          //There has to be a better way!! 
          if(! this.plans) 
          { 
           this.plans = new Plans(); 
    
    
           this.plans.fetch({ 
    
            success: function() 
            { 
             self.plansListView = new PlansListView({ collection : self.plans }); 
             $('#container').append(self.plansListView.render().el); 
             if(self.requestedID) self.planDetails(self.requestedID); 
            } 
           }); 
          } 
          else 
          { 
           this.plansListView = new PlansListView({ collection : this.plans }); 
           $('#container').append(self.plansListView.render().el); 
           if(this.requestedID) self.planDetails(this.requestedID); 
    
          } 
         }, 
    
         planDetails : function(id) 
         { 
    
          if(this.plans) 
          { 
           this.plansListView.close(); 
           this.plan = this.plans.get(id); 
    
           if(this.planView) this.planView.close(); 
            this.planView = new PlanView({ model : this.plan }); 
           this.planView.render(); 
          } 
          else{ 
    
           this.requestedID = id; 
           this.index(); 
          } 
    
          if(! this.plans) this.index(); 
         }, 
    
         newPlan : function() 
         { var plan = new Plan({name: 'Cool Plan', date: 'Monday', desc: 'This is a great app'}); 
          this.newPlan = new NewPlanView({ model : plan, collection: this.plans }); 
          this.newPlan.render(); 
         } 
        }); 
    
    
    
        var app = new AppRouter(); 
        Backbone.history.start(); 
    
    }); 
    
    
    
    
    
    
    
    
    })(jQuery); 
    
  • 答えて

    1

    リストをデータベースと同期になりたいので、あなたがデータあなたはインデックスページをヒットするたびにフェッチされています(すなわち、他の誰かがアイテムを追加しました。

    の場合はではありません。データが存在しないときだけフェッチします。

    ただし、の場合の場合は、リストを同期してください。それでもあなたは新しく追加されたアイテムをそれらの間にレンダリングすることを望みます。フェッチされたリストからマージするか、別のリストを使用して新しく追加されたデータを保持することができます。

    別のリストを使用する場合は、両方のリストをレンダリングするだけで済みます。保存されていないリストはおそらく、永続的なリストの上部または下部のいずれかに存在する必要があります。

    +0

    いいえ各インデックスビューでサーバーとの同期を行う必要はありません。しかし、あなたが話していたマージをどうやってお勧めしますか? –

    +0

    モデルをid、.get(id)で取得し、新しいフェッチされたリストでモデルを更新することができます。コレクションの.parse()メソッドを使用して、保存されていないすべてのモデルを新しいリストに追加します。 – rkw

    +2

    これは助けになるかもしれません:(コレクションのfetchメソッドのバックボーンのドキュメントから) "コレクションの内容を置き換える代わりに、着信モデルを現在のコレクションに追加する場合は、{add:true}をフェッチ。" – matiasfh

    0

    「削除」パラメータを探していると思います。フェッチ中にモデルがコレクションから削除されないようにします。

    this.plans.fetch({remove: false}) 
    

    fetchメソッドの詳細については、backbone documentationを参照してください。

    関連する問題