Backbone.js Добавление модели в выпуск коллекции - PullRequest
4 голосов
/ 14 декабря 2011

Я создаю тестовое приложение в Backbone.js (мое первое приложение, использующее Backbone).Приложение работает так:

  1. Загрузка данных с сервера "Планы"
  2. Создание списка планов и отображение на экране
  3. Есть кнопка для добавления новогоplan
  4. После добавления нового плана добавьте в коллекцию (не сохраняйте на сервере сейчас)
  5. перенаправьте на страницу индекса и покажите новую коллекцию (включая только что добавленный план)

Моя проблема связана с пунктом 5. Когда я сохраняю план, я добавляю модель в коллекцию, а затем перенаправляю в исходный вид.В этот момент я получаю данные с сервера.Когда я получаю данные с сервера, это перезаписывает мою коллекцию, и моя добавленная модель исчезает.

Как я могу предотвратить это?Я нашел способ сделать это, но это определенно не правильный путь вообще.Ниже вы найдете мои примеры кода для этого.Спасибо за помощь.

Представление PlanListView:

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();
    }   

ПОЛНЫЙ КОД (функция ($) {

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 );

Ответы [ 2 ]

1 голос
/ 14 декабря 2011

Загружаете ли вы данные каждый раз, когда нажимаете на страницу индекса, потому что хотите, чтобы список синхронизировался с базой данных (т. Е. Кто-то еще добавил элемент, и вы хотите, чтобы он отображался)?

Если это не случай, то то, что вы делаете, мне кажется правильным; вы выбираете только когда данные не существуют.

Если, однако, do хотите, чтобы список был синхронизирован; но вы все еще хотите, чтобы ваши недавно добавленные элементы отображались среди них; Вы можете объединить выбранный список или использовать другой список для хранения вновь добавленных данных.

Если вы используете другой список, вам просто нужно отобразить оба списка; несохраненный список, вероятно, должен существовать либо вверху, либо внизу постоянного списка, сгруппированных вместе.

0 голосов
/ 19 декабря 2013

Я думаю, что вы ищете параметр "удалить", он будет препятствовать удалению моделей из коллекции во время выборки.

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

См. документацию по магистрали для получения дополнительной информации о методе выборки.

...