gmac / backbone.epoxy

Declarative data binding and computed models for Backbone
http://epoxyjs.org
MIT License
614 stars 89 forks source link

Collection as a computed attribute dependency #38

Closed mabeyj closed 11 years ago

mabeyj commented 11 years ago

Hey, I'm currently experimenting with Epoxy and computed attributes are pretty sweet! Is it possible to use collections as dependencies for computed attributes? Whenever an add, remove, reset, or change event is triggered from a collection, the computed attribute gets updated.

Here's an example of what I'm trying to do:

var Cart = Backbone.Epoxy.Model.extend({
    defaults: function()
    {
        return {items: new Backbone.Collection};
    },
    computeds: {
        total: function()
        {
            return this.get('items').reduce(function(sum, item)
            {
                return sum + item.get('price');
            }, 0);
        }
    }
});

var cart = new Cart;
console.log(cart.get('total')); // 0

var item = new Backbone.Model({price: 5});
cart.get('items').push(item);
console.log(cart.get('total')); // 0 (should be 5)

item.set('price', 10);
console.log(cart.get('total')); // 0 (should be 10)
gmac commented 11 years ago

Sorry, this isn't natively supported. The main reason being that (as demonstrated by your example case) we end up mixing composition with data. What I mean is: a Collection should be composition; it's a unique element that must be constructed as a member of a model instance. A Collection does not directly serialize in and out of JSON format, therefore it shouldn't be stored as data within a model. As such, I'd recommend storing collections as members on the model class, and just wire up the appropriate events required to keep computed attribute values as needed. While that requires a couple extra lines in your code, I think it's better in the long run. In general, I've found Collections to be fairly difficult to automate behavior on because they do so many different things for so many different use cases. To fully automate bindings, you've got to handle a LOT of potential use cases, the bulk of which will never apply to any one given scenario.

jekuno commented 8 years ago

Also see https://github.com/gmac/backbone.epoxy/issues/25 regarding recomputing of computeds.

Also see http://epoxyjs.org/documentation.html#handler-collection Note that the collection binding does not register a "change" event on its collection to avoid generally superfluous updates. Instead, you may manually trigger an "update" event on the collection to refresh its bindings. For a working demonstration of the collection binding, see the Epoxy ToDos demo.