(disclaimer: this question is much simpler than the title suggests!)
I have a re-occuring problem in my program architecture with listening to changes against a model.
I have set-up some collections (much like in Backbone.js) which are just lightweight classes built around an array. The collection is a collection of models. When the user makes changes to a model I keep ending up with dreadful nested events. This is a typical, simple, scenario that I’m trying to avoid:
$("#user-details").on("click", "#save", onSaveClick);
function onSaveClick()
{
var givennames = $("#givenname").val(),
// Get the model from the collection
var user = users.get($(this).attr("data-id"));
// set the property
user.set("GivenNames", givennames);
// listen for the save event
$(user).on("save", function(){
// Alert the view
});
user.save(); // save event triggers a "save" event on the model
}
If the same user is saved twice the event gets added/fired multiple times. Is there a better pattern for this?
Should the event be bubbling up through the collection and handled that way perhaps?
Here’s an actual example (the one I’m most ashamed of)
$("#user-devices").on("click", ".device button", function(){
var button = $(this),
deviceId = $(this).closest(".device").attr("data-id"),
device = userDevices.get(deviceId);
$(device).on("activate", function(event, device){
button.removeClass("btn-danger").addClass("btn-success")
$("#activation-dialog").modal("show");
})
if (device.get("Active") === "1")
{
$("#reactivation-warning-dialog").modal("show");
$("#reactivation-warning-dialog .btn-primary").on("click", function(){
device.activate();
});
}
else
{
device.activate();
}
});
You could just check if the
saveevent is already binded, in that case not bind it again, like this:See working example
To put some sugar on top, we can make the “check if event exist” logic into a custom jquery pseudo-selector, that would be defined as follows:
Then you can use it this way:
Working example
UPDATE FOR JQUERY >= 1.8
Starting with jQuery 1.8 there were some changes to the events object which makes my above code not to work, see this excerpt from the jQuery 1.8 release notes:
So here I post the jQuery >= 1.8 updated versions for of my above examples:
Checking if the save event is already binded, in that case not bind it again:
And the custom jquery pseudo-selector: