BackboneJS utilizing a event aggregator

Standard

When creating dynamic single page applications (SPA) a project can become rather large containing multiple views. These views may need to share or be alerted if the other view changes. BackboneJS can alert views if models data changes using the listenTo method.

this.listenTo(this.model, 'change', this.render);

However, lets assume you do not wish to pass a reference to a model in each of the views. It would be nice to have a way to pass data between the views another way; hence an event aggregator.

To demonstrate this consider this simple wine application. A user has the ability to modify the wine name or year. When the user data is submitted a dispatcher event is triggered alerting the wineView to rerender the set contents.

The Application

The first step is to create each view and pass in the event aggregator.

var aggregator = _.extend({}, Backbone.Events);

var formView = new FormView({ag: aggregator, model: new WineModel()});
var wineView = new WineView({ag: aggregator});

The formView binds to the click of the setData event which will update our wine model data. It then uses the event aggregators trigger method to alert all other views listening (the wineView) of the new data. The wine data model is passed in the trigger so a reference to the wine model is not needed in the wineView.

var FormView = Backbone.View.extend({
    el: '#input',
    aggregator: null,
    initialize: function (options) {
        this.aggregator = options.ag;
        this.render();
    },
    events: {
        "click #setData": "setData",
        "click .reset": "reset"
    },
    render: function () {
        this.$el.html(formTemplate);
        return this;
    },
    setData: function () {
        if ($("#name").val() !== "") {
            this.model.set({name: $("#name").val()});
        }
        if ($("#year").val() !== "") {
            this.model.set({year: $("#year").val()});
        }
        this.aggregator.trigger("aggregateEvent", this.model);

        return false;
    },
    reset: function () {
        this.model.clear().set(this.model.defaults);
        this.aggregator.trigger("aggregateEvent", this.model);

        return false;
    }
});

The wineView binds to the event “aggregateEvent” and when it is fired rerenders the view using the model data passed from the formView.

var WineView = Backbone.View.extend({
    el: '#output',
    initialize: function (options) {
        _.bindAll(this, "render");
        options.ag.bind("aggregateEvent", this.render);
    },
    render: function (model) {
        var compiledTemplate = _.template(WineTemplate)(model.toJSON());
        this.$el.html(compiledTemplate);
        return this;
    }
});

To see this event aggregator in action checkout my Github page and checkout a working example.

Leave a Reply

Your email address will not be published.