Backbonejs event occurring multiple times

12,349

Solution 1

Since nobody answered I thought I would add some more info in case anyone runs into this. A good resource to explain what is happening (and offer a generic solution) is http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/. Also, the latest version of backbone has some new methods to allow unregistering of events from views.

Solution 2

I have the same headache this morning, but found small workaround which works like a charm for me.

The main idea is to avoid creating new View object every time we need to show something, instead I try to reuse old view object. In my case it looks like this :

   Overview: backBone.View.extend({
        el: $('#overviewTab'),

        dialog : null,

dialog is my field where im going to hold my view object

now on the callback that creates new view i do this:

showNewActivityDialog: function () {
            this.dialog = this.dialog || new window.RTB.Views.NewActivity();
            this.dialog.render();
            return false;
        },

in this case I don't create new views - i reuse a previously created, so I don't bind new events!
Hope it will works for you

Share:
12,349

Related videos on Youtube

AlexGad
Author by

AlexGad

Updated on March 19, 2020

Comments

  • AlexGad
    AlexGad about 4 years

    I have a view that displays items in a grid. If a button to create a new row is clicked, a popup window (use SimpleModal) is displayed to allow the user to save the row to the server. If all goes well, the window closes and the grid is refreshed. All works fine up to this point. If I now open the window a second time, the save record event will get called two times. If I close and open the window a third time, then the event will be called three times, etc. I have no idea why the event is getting rebound multiple times. Here are my two views:

    FieldList View:

    var fieldListView = Backbone.View.extend({
    el: "#centerbodycontent",
    initialize: function () {
        _.bindAll(this, 'render', 'addField');
    },
    
    render: function () {
        $(this.el).empty();
        $("#FieldGridTemplate").tmpl({ results: this.model }).appendTo(this.el)
        stripe($(this.el).find("tbody"));
        return this;
    },
    events: {
        "click a#addfield": "addField"
    },
    addField: function (e) {
        window.appController.popup = new fieldFormView({ model: new fieldModel({ contenttype_id: this.model.id }) });
        window.appController.popup.render();
    }
    

    });

    Form View (this is what gets called for the popup)

    var fieldFormView = Backbone.View.extend({
    el: "#popupwindowcontent",
    
    events: {
        "click #savefieldandnew": "savefield",
        "click #savefieldandclose": "savefield",
        "change input,textarea,select": "changeField"
    },
    render: function () {
        var formWrapper = $(this.el).find(".modal-form")[0];
        $(formWrapper).empty();
        $("#FieldFormTemplate").tmpl({ results: this.model }).appendTo(formWrapper)
        OpenForm(this.el, "Add Field", 450, 600);
        return this;
    },
    // automatically updates the model during field changes
    changeField: function (e) {
        var changeobj = new Object;
        switch (e.target.type) {
            case "radio":
                changeobj[e.target.id] = parseInt($(e.target).val());
                break;
            case "checkbox":
                changeobj[e.target.id] = $(e.target).is(":checked");
                break;
            default:
                changeobj[e.target.id] = $(e.target).val();
                break;
        }
    
        if (e.target.id.toLowerCase() == "name") {
            var k = $(this.el).find("#key");
            if (jQuery.trim(k.val()).length == 0)
                k.val($(e.target).val().replace(/[^a-zA-Z0-9]+/g, '').toLowerCase());
    
            var l = $(this.el).find("#label");
            if (jQuery.trim(l.val()).length == 0)
                l.val($(e.target).val());
        }
    
        var options = { silent: true };
        this.model.set(changeobj, options);
    },
    savefield: function (e) {
        var kcode = (e.which);
        var thiz = this;
        var m = this.model;
        var nextaction = e.target.id;
        alert(nextaction);
        if (kcode == 0 || kcode == 1 || kcode == 32) {
            e.preventDefault();
            if ($("#contentfieldform").validate({
                rules: {
                    name: { required: true },
                    label: { required: true },
                    key: { required: true }
                }
            }).form()) {
                m.save(null, {
                    headers: { "If-Match": m.get("version") },
                    error: function (model, response) {
                        var errResp = JSON.parse(response.responseText);
                        popupException("Content Type Modification Error", errResp.errors[0].message);
                    },
                    success: function (model, response) {
                        window.appController.popup.model = new fieldModel;
                        $.pnotify({
                            pnotify_title: 'Field Saved',
                            pnotify_text: 'The field was saved successfully.'
                        });
    
                        if (nextaction == "savefieldandclose") {
                            $.modal.close();
                        }
                    }
                });
            }
        }
    }
    
    • AlexGad
      AlexGad about 13 years
      OK, it finally hit me what was going on. For anyone who is running into a similar problem, be careful what the ID for the el in your view is. I was using the same ID for the el in multiple views and this was causing no end of problems especially since I was not removing the el for new popups but rather the children underneath the el in the DOM. The result was the views and events were still hanging off the el and were accumulating every time I opened the popup again with a new view since the view had its own events that were added to the previous ones.
    • Ilia Choly
      Ilia Choly over 12 years
      you can answer your own question.

Related