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);
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);
Share
Improve this question
asked Feb 24, 2012 at 23:29
MatthewMatthew
13.3k6 gold badges43 silver badges45 bronze badges
4
-
hmmm maybe my question is not clear, I want to know how I can pass data to the
change:attr
handler, right now that event is being fired "automagically" by backbone, whenever I callset()
on my model. – Matthew Commented Feb 25, 2012 at 0:17 - What data do you want to pass? You'll have access to the model already and you'll know which attribute has been changed. – tkone Commented Feb 25, 2012 at 0:25
- I need to pass the nature of the change, so if the attr value increased vs decreased i want to know. I guess I can keep a cache of the old value and pare them, I don't think this is very clean... – Matthew Commented Feb 25, 2012 at 2:32
- 1 Ah. That is easy. It's already there. See my answer below. – tkone Commented Feb 25, 2012 at 12:04
3 Answers
Reset to default 12Here 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.
Just look at previousAttributes()
You can then pare:
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
What if you fire your own custom event after listening to the change event?
handler: function(increased) {
this.model.trigger('my-custom-event', stuff, you, want);
},
myHandler: function(stuff, you, want){
// Do it...
}
// ...
this.model.on("change:attr", this.handler, this);
this.model.on('my-custom-event, this.myHandler, this);