Question

It's my first post here so please be nice ;) I'm trying to create a Backbone+requireJS sample app and I have stumbled upon a strange problem. In my views initialize function I bind to models change event by

this.model.on("change", this.change());

Event is triggered correctly when data is loaded and all is fine. In my view I also bind to a click event. On click I try to change one of the properties and I was hoping for a change event, but it never came.

I was trying some stuff recommended here on stackoverflow (here, here, and there) but with no luck.

In my guts I feel it has to do with event binding. When I tried to bind again to models on change event inside click callback it started to work. So now I sit here and I'm, hm, confused. Could someone shed some light on this issue?

My View:

define(
[
  'jquery',
  'underscore',
  'backbone',
  'text!templates/news/newsListItem.html'
 ],
 function($, _, Backbone, newsListItemTemplate)
 {
    var NewsListItemViewModel = Backbone.View.extend({
        tagName: 'li',
        events: {
            "click a" : "onLinkClick"
        },
        initialize: function(){
            this.model.on("change", this.changed());
        },
        render: function()
        {
            this.$el.html(_.template(newsListItemTemplate, this.model.toJSON()));
        },
        changed: function()
        {
            this.render();
            console.log("changed");
        },
        //GUI functions
        onLinkClick: function(e)
        {
            console.log("click!");
            this.model.toggle();
            this.model.on("change", this.changed());

        }

    });

    var init = function(config){
        return new NewsListItemViewModel(config);
    }

    return {
        init : init
    }
 }

);

My Model:

define(
['jquery', 'underscore', 'backbone'],
function($, _, Backbone){

    var NewsListItemModel = Backbone.Model.extend({
        toggle: function() {
            this.set('done', !this.get('done'));
            this.trigger('change', this);
        }
    });

    var init = function(data)
    {
        return new NewsListItemModel(data);
    }

    return {
        init: init,
        getClass: NewsListItemModel
    };
}

);

Thanks for any input :)

Was it helpful?

Solution

First, you should use a function as event handler - not its result. Hence, change the line into this:

this.model.on("change", this.changed.bind(this));

As it stands now, you actually fire this.changed() function just once - and assign its result (which is undefined, as the function doesn't have return statement) to be the model's change event handler.

Second, you shouldn't rebind this handler in onLinkClick: once bound, it'll stay here. It looks like it's more appropriate to trigger this event instead:

onLinkClick: function(e)
{
  console.log("click!");
  this.$el.toggle();
  this.model.trigger('change');
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top