Up tonight, a bit of research for Recipes with Backbone. As Nick Gauthier continues to work through new recipes, I am working through some of our existing chapters to beef them up. Tonight, I am going to get started on the View Signature recipe.
The idea behind the view signature is to retain information from previous renders to decide if a model change requires an re-render. In my calendar app:
...the easiest way to trigger a change event is to navigate to a later month, change an appointment in a separate window, then navigate back to the same month. The collection caching solution that I have implemented will display the original view immediately, then fetch any changes from the server, forcing a re-render.
Currently, updates are implemented by binding the View's
update()
method to the model's change event: var Appointment = Backbone.View.extend({
initialize: function(options) {
// ...
options.model.bind('change', this.update, this);
},
// ...
update: function() {
console.log("[Appointment#update]");
$(this.el).html(this.template(this.model.toJSON()));
return this;
},
// ...
});
But, this will cause re-renders even if minor details change. Really, the only reason that I would want to update the Appointment view is if the appointment's title changes.For that, I build up a view signature that is tied only to the title. If this title-bound signature changes after a
change
event, only then will I redraw the appointment: var Appointment = Backbone.View.extend({
// ...
update: function() {
console.log("[Appointment#update]");
var signature = $.param({
title: this.model.get('title')
});
if (this.signature === signature) return this;
console.log("[Appointment#update] sig change: " + this.signature + " -> " + signature);
this.signature = signature;
$(this.el).html(this.template(this.model.toJSON()));
return this;
},
// ...
});
Now, if I update the title of an appointment in a separate window, force a collection cache refresh in my current window, I see the signature has changed in Chrome's Javascript console:More importantly, the appointment in the calendar is updated.
But, if I repeat the exercise, only updating the description of the appointment (and not the title):
Then a collection cache refresh omits the redraw since the view's signature has not changed:
With a view signature implementation in place, I call it a night here. Up tomorrow: taking this up a notch.
Day #179
I'm sure that's an appropriate time to use a signature, but in your example, why not just bind to 'change:title'. This way, your view will only be notified when the title changes.
ReplyDeleteoptions.model.bind('change:title', this.update, this);
Oops, sorry for the typo. My last comment should have said "I'm sure there's an appropriate time...".
ReplyDeleteHahaha. Good point. I really should have made my example dependent on title and description, then added a bunch of unrelated, but oft-changing additional attributes.
ReplyDeleteI was more concerned with playing with my new toy and not concerned enough with setting a good context. Thanks for the feedback -- much appreciated!