Multiple Views and Sub Views with 1 collection in

2019-09-15 03:54发布

问题:

I have issue in rendering Shopping Bag Views using Backbone for my website.

I am using 1 collection for all Bag Views (“Quick_View” of items list & “Normal_View” of Items list). Also I created “Item_View”, which is being used to render each item in both the Views.

It is a SPA (Single Page Application) and “Quick_View” is initiated and rendered for all Backbone routes and hidden by default. Whenever user clicks on “Quick_View” link from any page it is showing. There is no route defined for it.

The “Normal_View”, can be accessed using Checkout button given in “Quick_View”. It is bind with “domain/checkout” route.

When I access “Normal_View” from “Quick_View” check button; it works fine and both (Quick and Normal) views are in Sync. Means, when we add, delete, update any item in any of the View, both Views are getting updated accordingly.

But when I access “domain/checkout” route directly in a new browser, both views are getting rendered fine, but they are not in sync. Means, change in 1 view does not update another view.

The reason, I tracked is, when I access “Normal_View” through “Quick_View”, model for each item in both the Views having same CID, so the both Views are in sync, if there is any change in a model from any of the View.

And, when I access “Normal_View” directly, model for each item in both the views are not having same CID, so they do not work as expected.

There are few more points to consider:

  • Collection is firing reset event twice for “Quick_View” and each item in “Quick_View” is rendering twice.
  • When, I access “Normal_View” (in either way), “Quick_View” is again getting rendered but once “Normal_View” rendering is over.

// Main View

var mainView = Backbone.View.extend({
    el: 'body',
    template: {
        header: Handlebars.compile(headerTemplate),
        mainNav: Handlebars.compile(mainNavtemplate),
        footer: Handlebars.compile(footerTemplate)
    },
    initialize: function() {
        _.bindAll();
        AW.collection.bag = new bagCollection();
        //AW.collection.bag.fetch({reset:true});
    },
    render: function() {
        this.$el.html(this.template());
        this.loadSubView('bagQV');
    },
    loadSubView: function(subView) {
        switch(subView) {
            case 'home' :
                if(!AW.view.home) AW.view.home = new homepageView();
                AW.view.home.render();
                break;
            case 'bagQV'    :
                if(!AW.view.bagQV) AW.view.bagQV = new bagQuickView({collection: AW.collection.bag});
                //AW.view.bagQV.render();
                break;
            case 'checkout' :
                if(!AW.view.checkout) AW.view.checkout = new checkoutView({collection: AW.collection.bag});
                AW.view.checkout.render();
                break;
        }
    }
});

// Single Item View

var bagItemView = Backbone.View.extend({
    tagName: 'tr',
    template:   Handlebars.compile(bagItemTemplate),
    initialize: function() {
        _.bindAll(this);
        this.listenTo(this.model, 'change', this.render);
        this.listenTo(this.model, 'remove', this.removeItem);
        $(document).on('keyup', this.listenKeyboard);
    },
    events: {
        'click .qtyInput .button'           : 'updateItem',
        'click .controls a.remove'          : 'removeModel'
    },
    render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        this.$el.attr('data-id',this.model.cid);            
        return this;
    },
    updateItem: function(e) {
        e.preventDefault();
        e.stopPropagation();
        var newQty = this.$el.find('.qtyInput input').val();
        var newAmt = newQty * parseFloat(this.model.get('prodRate').replace('$',''));
        this.model.set({prodQty: newQty, amount: '$' + newAmt});
        this.cancelEdit(e);
    },
    removeModel: function(e) {
        e.preventDefault();
        e.stopPropagation();
        if(AW.collection.bag) AW.collection.bag.remove(this.model);

    },
    removeItem: function() {
        this.$el.remove();
    }
});

// Bag Quick View

var bagQuickView = Backbone.View.extend({
    tagName:    'div',
    id:         'myBagQV',
    template:   Handlebars.compile(bagQuickViewTemplate),
    initialize: function() {
        _.bindAll(this);
        this.collection.fetch({reset:true});
        //this.collection.bind("reset", _.bind(this.render, this));
        this.listenTo(this.collection, 'add', this.addItem);
        this.listenTo(this.collection, 'reset', this.render);
    },
    render: function() {
        if($('#myBagQV').length == 0) {
            this.$el.html(this.template());
            $('body').append(this.el);
        }
        this.addAllItems();
        return this;
    },
    addItem: function(item) {
        var parent = this;
        var itemView = new bagItemView({model: item});
        $('#itemsInBag table tbody').append(itemView.render().el);
    },
    addAllItems: function() {
        if(this.collection.length > 0) {
            $('#itemsInBag table tbody').html('');
            this.collection.each(this.addItem, this);
        }
    },
});

// Normal Bag View

var bagView = Backbone.View.extend({
    tagName:    'div',
    id:         'myBag',
    template:   Handlebars.compile(checkoutBagTemplate),
    initialize: function() {
        _.bindAll(this);
        this.collection.fetch({reset:true});
        //this.collection.bind("reset", _.bind(this.render, this));
        this.listenTo(this.collection, 'add', this.addItem);
        this.listenTo(this.collection, 'reset', this.render);
    },
    render: function() {
        this.$el.html(this.template());
        $('#checkoutContainer #details').append(this.el);
        this.addAllItems();
        return this;
    },
    addItem: function(item) {
        var parent = this;
        var itemView = new bagItemView({model: item});
        this.$el.find('table tbody').append(itemView.render().el);
    },
    addAllItems: function() {
        if(this.collection.length > 0) {
            this.$el.find('table tbody').html('');
            this.collection.each(this.addItem, this);
        }
    }
});

Looking for you help. Thank you in advance

Cheers, Vikram