LinkXXI
LinkXXI

Reputation: 314

Backbone.js firing other view's event

I'm working with an API and Backbone.js at the moment.

I have two views, both render to the same document element #viewContainer. Both of these views render a table with a couple strings to decribe them and a button that opens a form in a modal.

View 1

App.Views.TaskList = Backbone.View.extend({
    el: "#viewContainer",
    tagName: 'tr',
    events: {
        "click button": "showTaskForm"
    },
    showTaskForm: function (event) {
        event.preventDefault();
        var id = $(event.currentTarget).data("id");
        var item = this.collection.get(id);
        var formView = new App.Views.Form({
            model: item
        });
        formView.render();
    },
    render: function () {
        changeActive($('#tasksLink'));
        var template = _.template($("#taskList").html(), {});
        $('#viewContainer').html(template);
        // loop and render individual tasks.
        this.collection.each(function (model) {
            var variables = {
                name: model.get('name'),
                button: model.getButton()
            };
            var template = _.template($("#task").html(), variables);
            $("#taskTable tbody").append(template);
        });
    },
    collection: App.Collections.Tasks,
});

View 2

App.Views.ProcessList = Backbone.View.extend({
    el: "#viewContainer",
    tagName: 'tr',
    events: {
        "click button": "showStartForm"
    },
    showStartForm: function (event) {
        event.preventDefault();
        var id = $(event.currentTarget).data("id");
        var item = this.collection.get(id);
        var formView = new App.Views.Form({
            model: item
        });
        formView.render();
    },
    collection: App.Collections.Processes,
    render: function () {
        changeActive($('#processLink'));
        var template = _.template($("#processList").html(), {});
        $('#viewContainer').html(template);
        this.collection.each(function (model) {
            var variables = {
                processId: model.get('id'),
                processName: model.get('name'),
                button: model.getButton()
            };
            var template = _.template($('#process').html(), variables);
            $('#processList tbody').append(template);
        });
    } });

Neither of these views are rendered by default, both need to be activated by a button on the page and they over-write each other in the DOM. However, which ever view is rendered first, the click event of the buttons in that view are the ones that are always fired.

If there is any more information needed from me let me know and I will edit the question.

Upvotes: 0

Views: 95

Answers (3)

cs_stackX
cs_stackX

Reputation: 1527

As other posters have pointed out, you need to watch out for 'zombie' views (i.e. making sure you undelegate events). If you're building even a moderately complex app, you'll want something that can scale. I find this pattern useful:

var BaseView = Backbone.View.extend({
    render: function () {
      this.$el.html(this.template());
      return this;
    },
    close: function () {
      if (this.onClose) this.onClose();

      this.undelegateEvents();
      this.$el.off();
      this.$el.remove();
    }
});

Then whenever you build a view you can do:

var view = BaseView.extend({
   //your code
   //now the .close() method is available whenever you need to close
   //a view (no more zombies!).
});

Upvotes: 0

Stephen Thomas
Stephen Thomas

Reputation: 14053

Be sure to call undelegateEvents() in the first view when you render the second.

Upvotes: 1

bioball
bioball

Reputation: 1359

Since you're listening for events on the same elements, essentially you attached two listeners for click events on the same button, and when you change your views you are not cleaning up these listeners.

Here's an article that talks about managing events on view change, which should be really helpful to you.

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

Upvotes: 0

Related Questions