goldfinger
goldfinger

Reputation: 1115

binding collection change to view render

In spite of the many questions/answers on this same topic on StackOverflow and elsewhere, I still don't understand how to proceed. I would like a change in my collection to trigger the render function in my view. View has a collection, not a model -- so the many examples I see for model.bind are not applicable. Apparently collection.bind is not a legitimate binding. Here's my view code. What should I add in initialize so that when orderedPrefs (collection) has a change, the view's render function is called?

headerView = Backbone.View.extend({

        el: $('#' + targetdiv),
        collection: orderedPrefs,
        events: {
            "click .scheduleheader": "clicked"                               // dependency here on scheduler.js class naming .scheduleheader

        },
        initialize: function () {
            _.bindAll(this, "render");

        },
        render: function () {
            alert('render!!');
        },

..... .....

Upvotes: 2

Views: 930

Answers (2)

Andrei Rosca
Andrei Rosca

Reputation: 1097

These should work inside the initialize function:

this.collection.on("add", this.render);
this.collection.on("remove", this.render);
this.collection.on("reset", this.render);

If they don't, you have a problem with the collection attached to the view. You should not use global "orderedPrefs".

Backbone docs state:

When creating a new View, the options you pass are attached to the view as this.options, for future reference. There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName and attributes.

When instantiating your view, you need to pass the collection like this:

new headerView({ collection: orderedPrefs });

If you want to track changes in the collection models, you should do it in a different view:

var ModelView = Backbone.View.extend({
    initialize: function() {
        _.bindAll(this, "render");
        this.render();
        this.model.on("change",this.render);
    },
    render: function() {
        $(this.el).html("model view markup"); // you should use templating
        return this;
    }
});

var headerView = Backbone.View.extend({
    el: $('#' + targetdiv),
    initialize: function () {
        _.bindAll(this, "render");
        this.collection.on("add", this.render);
        this.collection.on("remove", this.render);
        this.collection.on("reset", this.render);
    },
    render: function () {
        var self = this;
        this.collection.each(function(collectionModel){
            var view = new ModelView({ model : collectionModel });
            $(self.el).append(view.el);
        });
    }
});

Upvotes: 3

McGarnagle
McGarnagle

Reputation: 102743

You can bind using collection.on to the "add" and "remove" events. See the documentation under Add for an example of usage.

this.collection.on("add", this.render);

If you're using Backbone version 0.9.0 or newer, then you can bind multiple events in the same statement:

this.collection.on("add remove", this.render);

Note also that "bind" should work the same as "on":

bind and unbind have been renamed to on and off for clarity, following jQuery's lead. The old names are also still supported.

Upvotes: 1

Related Questions