0

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?

Paul T. Rawkeen
  • 3,994
  • 3
  • 35
  • 51
  • Do you need the original collection after creating the filtered one? – Spike Oct 01 '15 at 15:02
  • @Spike, yes bec. I'm creating several collections from retrieved data. And this filtering is the first one. – Paul T. Rawkeen Oct 01 '15 at 15:05
  • Are these several collections (and this filtered collection) only used for views, or do you use them outside views for computations etc.? – Spike Oct 01 '15 at 15:08
  • @Spike, sorry for late answer. Yes I am using these collections later for computing the result data. There is a bit more than just passing them to the view and render. – Paul T. Rawkeen Oct 01 '15 at 20:50

2 Answers2

0

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();
Paul T. Rawkeen
  • 3,994
  • 3
  • 35
  • 51
0

If you're creating the filtered collection only to use it in a view, it is better (and more correct) to use the original collection and let the view render only the items you want. For example (inside the view class):

render: function() {
    this.model.each(function(m) {
         if(~m.get('partner_id') === 0)
             return;
         /* render m here */
    });
}

The rationale is that the view represents the original collection.


(If you need several filtered views of the same collection, you can use a single view class for all of them and pass it a filter function:

initialize: function(filter) {
    this.filter = filter;
}
render: function() {
    this.model.each(function(m) {
         if(!this.filter(m))
             return;
         /* render m here */
    });
}

Then create a view like this: new FilteredView(function(m) {return ~~m.get('partner_id') === 0;})

Spike
  • 725
  • 5
  • 12
  • Thanks for the effort, I tried `filter` function to filter unnecessary models in view as first approach, but the derivatives of main collection are tightly coupled and the latter depends on, let say, the length of first, thus just filtering is not quite applicable in my case, bec. collection still consists of all models I retrieved and this is the case I was actually solving. – Paul T. Rawkeen Oct 01 '15 at 20:58