I'm pretty new to Backbone so excuse me if this question is a little obvious. I am having problems with a collection inside of a model. When the collection changes it doesn't register as a change in the model (and doesn't save).
I have set up my model like so:
var Article = Backbone.Model.extend({
defaults: {
"emsID" : $('html').attr('id')
},
initialize: function() {
this.tags = new App.Collections.Tags();
},
url: '/editorial_dev.php/api/1/article/persist.json'
});
This works fine if I update the tags collection and manually save the model:
this.model.tags.add({p : "a"});
this.model.save();
But if the model is not saved the view doesn't notice the change. Can anyone see what I am doing wrong?
I'm pretty new to Backbone so excuse me if this question is a little obvious. I am having problems with a collection inside of a model. When the collection changes it doesn't register as a change in the model (and doesn't save).
I have set up my model like so:
var Article = Backbone.Model.extend({
defaults: {
"emsID" : $('html').attr('id')
},
initialize: function() {
this.tags = new App.Collections.Tags();
},
url: '/editorial_dev.php/api/1/article/persist.json'
});
This works fine if I update the tags collection and manually save the model:
this.model.tags.add({p : "a"});
this.model.save();
But if the model is not saved the view doesn't notice the change. Can anyone see what I am doing wrong?
Share Improve this question edited Dec 5, 2011 at 18:13 Tomasz Nurkiewicz 341k71 gold badges711 silver badges678 bronze badges asked May 25, 2011 at 15:34 Ad TaylorAd Taylor 2,7755 gold badges27 silver badges32 bronze badges2 Answers
Reset to default 12initialize: function() {
this.tags = new App.Collections.Tags();
var model = this;
this.tags.bind("change", function() {
model.save();
});
},
Bind to the change
event on the inner collection and just manually call .save
on your outer model.
This is actually an addendum to @Raynos answer, but it's long enough that I need answer-formatting instead of comment-formatting.
Clearly OP wants to bind to
change
andadd
here, but other people may want to bind todestroy
as well. There may be other events (I'm not 100% familiar with all of them yet), so binding toall
would cover all your bases.remove
also works instead ofdestroy
. Note that bothremove
anddestroy
fire when a model is deleted--firstdestroy
, thenremove
. This propagates up to the collection and reverses order:remove
first, thendestroy
. E.g.model event : destroy model event : remove collection event : destroy collection event : remove
There's a gotcha with custom event handlers described in this blog post.
Summary: Model-level events should propagate up to their collection, but can be prevented if something handles the event first and calls
event.stopPropagation
. If the event handler returnsfalse
, this is a jQuery shortcut forevent.stopPropagation(); event.preventDefault();
Calling
this.bind
in a model or collection refers to Underscore.js's bind, NOT jQuery/Zepto's. What's the difference? The biggest one I noticed is that you cannot specify multiple events in a single string with space-separation. E.g.this.bind('event1 event2 ...', ...)
This code looks for the event called
event1 event2 ...
. In jQuery, this would bind the callback toevent1
,event2
, ... If you want to bind a function to multiple events, bind it toall
or callbind
once for each event. There is an issue filed on github for this, so this one will hopefully change. For now (11/17/2011), be wary of this.