Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone this confusion

I have the following code:

var GoalPanelView = Backbone.View.extend({

    // Bind to the goal panel DOM element
    el: $("#sidebar-goals"),    

    // Initialize the collection
    initialize: function() {
        this.collection = Goals;
        this.collection.bind('add', this.appendItem);
    },

    // Create a new goal when a user presses enter in the enter goal input
    createOnEnter: function(e) {
        if (e.keyCode != 13) return;
        this.addItem();
        //Goals.create(this.newAttributes());           
    },

    // Add the goal item to the goal list
    addItem: function() {
        var goal = new Goal();
        goal.set(this.newAttributes());
        var goalsElem = this.el;
        this.collection.add(goal);
        $(this.el).children("#enter-goal").val('');
    },

    // Append DOM element to the parent el
    appendItem: function(item) {
        var goalView = new GoalView({
            model: item,
        });
        $(this.elem).append(goalView.render().el);
    }

});

My problem is inside of the appendItem function. When I use this inside of the appendItem function, I believe that it thinks that the this refers to the this.collection rather than the GoalPanelView. How would I get the this to refer to the GoalPanelView rather than the collection? I tried to pass another variable into the appendItem function which held the contents of this.elem, but it didn't seem to work.

One thing that worked was when I moved the appendItem function into the collection and changed the initialization to bind to this.collection.bind('add', appendItem); but I do not want to put the view stuff into the collection logic.

like image 925
egidra Avatar asked Mar 26 '12 23:03

egidra


2 Answers

You can add a scope when binding an event handler, like so:

this.collection.bind('add', this.appendItem, this);

The scope sets the value of this inside the handler. In you case, the current object.

Edit: Javascript Garden has a great explaination why this.appendItem does not actually carry the scope of the function itself, it's just a function pointer, not a method pointer. One of the quirks of Javascript..

Edit 2 Backbone Reference - Events / on

like image 171
Ben Avatar answered Sep 28 '22 12:09

Ben


Just to update (as of Backbone 0.9.2), the proper way to do this is:

initialize: function() {
    this.collection.on("add", this.appendItem, this);
    ...
}


Depending on your use case, you may also want to consider:

initialize: function() {
    this.listenTo(this.collection, "add", this.appendItem);
    ...
}
like image 27
Kabir Sarin Avatar answered Sep 28 '22 13:09

Kabir Sarin