Search code examples
javascriptbackbone.jsmarionettebackbone-eventsbackbone.js-collections

Separating a `Backbone` collection (events issue)


So, the problem is next: I receive large collection of prices and there are prices for specific, let say, partners. Thus collection contains some kind of groups denoted by partner_id.

I filtering this collection (using collection.filter() in initialize method), to obtain different "format" of data for subsequent views.

var BasePrices = new Collections.ProductPrices( // Creating the same collection type
    this.model.get('prices').filter(function (m) { // But a bit narrowed
        return ~~m.get('partner_id') === 0; // leaving prices without `partner_id`
    })
);

Later I pass this newly done collection to the view that is managing the list of base prices.

The problem itself is that I'm subscribing on events of this newly done collection, but events of models that remained there after .filter() are firing their events to the old collection that lays under this.model.get('prices'), but newly added models firing their events correctly (to the BasePrices collection).

I couldn't understand why its happening so. I can presume that there is smth. related with reference of model to collection (model.collection property), but why it is not updated when I created brand new collection and how to solve the issue?


Solution

  • And the problem was indeed in references and cloning (not cloning, actually). The point is that we need to clone everything to the new collection. Clone ... not copy, not pass (by reference as we know) - clone.

    var BasePrices = new Collections.ProductPrices() // Creating the same collection type
    
    _(this.model.get('prices').models) // Implicitly `_.chain`ing
        .filter(function (m) { return ~~m.get('partner_id') === 0; }) // leaving prices without `partner_id`
        .map(function (m) { return m.toJSON(); }) // converting each model to raw object
        .tap(function (a) { c.add(a); }) // adding all models at once
        .value(); // evaluating chain
    

    ! More elegant ways of solving this problem are highly appreciated.


    UPD: Just to keep chaining consistent here is one-liner for lodash.

    var BasePrices = _(this.model.get('prices').models)
            .filter(function (m) { return ~~m.get('partner_id') === 0; })
            .map(function (m) { return m.toJSON(); })
            // creating collection passing all models in constructor
            .thru(function (a) { return new Collections.ProductPrices(a); })
            .value();