Search code examples
javascriptbackbone.jspagination

Backbone : Make collection from slice of another collection


I'd like to have a paginated view of a collection. I tried using Backbone.Paginator but I just couldn't make it work.

I figured I'd do the pagination myself and I thought it would be a good idea to have my full collection, and then send the view a small collection of the big one, and do this every time someone clicks on 'next'.

I tried doing this but it doesn't work :

var purchaseCollection = new purchaseItemCollection({url:endpoints.purchases});

purchaseCollection.fetch();

var purchaseRangeCollection = new Backbone.Collection(purchaseCollection.models),
    purchaseView = new purchaseItemCollectionView({collection:purchaseRangeCollection});

My second collection is only made of one model when it should have severals.

I'm wondering if this is even the best way to do it.

Any advice on how to split a collection into collections, or how to do it in another way would really be appreciated!


Solution

  • You could use a custom object to control a collection representing the list of models currently selected.

    For example,

    var Slicer = function(opts) {
        opts || (opts = {});
    
        // your big collection
        this.collection = opts.collection || new Backbone.Collection();
    
        // a collection filled with the currently selected models
        this.sliced = new Backbone.Collection();
    };
    
    _.extend(Slicer.prototype, Backbone.Events, {
        // a method to slice the original collection and fill the container
        slice: function(begin, end) {
            var models = this.collection.models.slice(begin, end);
            this.sliced.reset(models);
    
            // triggers a custom event for convenience
            this.trigger('sliced', this.sliced);
        }
    });
    

    You would then create an instance of this controller and either listen to the custom event sliced on this object or on a reset event on the sliced collection to update your view:

    var controller = new Slicer({
        collection: purchaseCollection
    });
    controller.on('sliced', function(c) {
        console.log('sliced', c.pluck('id'));
    });
    controller.sliced.on('reset', function(c) {
        console.log('reset', c.pluck('id'));
    });
    

    And a demo to play with http://jsfiddle.net/nikoshr/zjgkF/

    Note that you also have to take into account the asynchronous nature of fetch, you can't immediately work on the models. In this setup, you would do something like

    var purchaseCollection = new purchaseItemCollection(
        [], // you have to pass an array
        {url:endpoints.purchases} // and then your options
    );
    purchaseCollection.fetch().then(function() {
        // do what you want
        // for example
        controller.slice(0, 10);
    });