Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwriting a Backbone Models Change Event

I think what I want to do is pretty simple I just don't know how to do it. I would like to fire my own event when one of my models attributes changes for the purpose of passing some data to the event handler (whether the change was an increase or decrease in value).

Basically I want my handler to do this in the view

handler: function(increased) {
   if(increased) {
      alert("the value increased")
   }
   else {
      alert("the value decreased")
   }
}

// ...

this.model.on("change:attr", this.handler, this);
like image 604
Matthew Avatar asked Feb 24 '12 23:02

Matthew


2 Answers

Here you go: You basically listen for change:myvar. When a change occurs you use your model's previous() to get the old value. Depending on whether it increased or decreased you fire the appropriate event. You can listen to these events as shown in the initialize().

(function($){

    window.MyModel = Backbone.Model.extend({

        initialize: function () {
            this.on('change:myvar', this.onMyVarChange);
            this.on('increased:myvar', function () {                  
                console.log('Increased');                
            });
            this.on('decreased:myvar', function () {                  
                console.log('Decreased');                
            });
        },

        onMyVarChange: function () {
            if (this.get('myvar') > this.previous('myvar')) {
                this.trigger('increased:myvar');  
            } else {
                this.trigger('decreased:myvar');
            }
        }            
    });

    window.mymodel = new MyModel({myvar: 1});
    mymodel.set({myvar: 2});
    mymodel.set({myvar: 3});
    mymodel.set({myvar: 1});

})(jQuery);​

Running the above will print "Increased", "Increased", "Decreased" to your console.

like image 104
ggozad Avatar answered Oct 05 '22 23:10

ggozad


Just look at previousAttributes()

You can then compare:

If(this.get(attr) > this.previousAttributes()[attr]){
    console.log('bigger');
} else {
    console.log('smaller');
}

If you use that in your change event handler you're all set. No need for a custom trigger or a ton of code.

EDIT

This is from my Backbone.Validators project and how I obtain the list of all attributes which have changed during the validation step:

var get_changed_attributes = function(previous, current){
    var changedAttributes = [];
    _(current).each(function(val, key){
        if(!_(previous).has(key)){
            changedAttributes.push(key);
        } else if (!_.isEqual(val, previous[key])){
            changedAttributes.push(key);
        }
    });
    return changedAttributes;
};

This requires Underscore 1.3.1 because it's using _.has. If you can't upgrade that's an easy thing to replace though. In your case you'd passing this.previousAttributes() and this.attributes

like image 32
tkone Avatar answered Oct 05 '22 23:10

tkone