Skip to content Skip to sidebar Skip to footer

Listen For Changes Against An Object In An Array Without Nesting Event Listeners

(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

Solution 1:

You could just check if the save event is already binded, in that case not bind it again, like this:

// if no 'save' event already bindedif (!$(user).data('events') || !$(user).data('events').save) { 
    // listen for the save event
    $(user).on("save", function(){
        // Alert the view
    });
}

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:

$.expr[':'].hasEvent = function(obj, idx, meta, stack) {
    return ($(obj).data('events') != undefined 
            && $(obj).data('events')[meta[3]] != undefined);
};

Then you can use it this way:

$(user).not(":hasEvent(save)").on("save", function(){
     // Alert the view
});

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:

$(element).data(“events”): In version 1.6, jQuery separated its internal data from the user’s data to prevent name collisions. However, some people were using the internal undocumented “events” data structure so we made it possible to still retrieve that via .data(). This is now removed in 1.8, but you can still get to the events data for debugging purposes via $._data(element, "events"). Note that this is not a supported public interface; the actual data structures may change incompatibly from version to version.

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:

// if no 'save' event already bindedif (!$._data(user, 'events') || !$._data(user, 'events').save) { 
    // listen for the save event
    $(user).on("save", function(){
        // Alert the view
    });
}

And the custom jquery pseudo-selector:

$.expr[':'].hasEvent = function(obj, idx, meta, stack) {
    return ($._data(obj, 'events') != undefined 
            && $._data(obj, 'events')[meta[3]] != undefined);
};

Solution 2:

I agree that the nested listener is a little weird--after all, you're already in a save listener, just for the button click rather than the model object.

I think I'd rewrite the code something like this:

$("#user-devices").on("click", ".device button", function(){

    var button = $(this),
        deviceId = $(this).closest(".device").attr("data-id"),
        device = userDevices.get(deviceId);

    if (device.get("Active") === "1")
    {
        $("#reactivation-warning-dialog").modal("show");
        $("#reactivation-warning-dialog .btn-primary").on("click", device.activate);

    }
    else
    {
        device.activate();
    }
});

//in the device "class"
{ 
   ...
   ...

   activate: function() {
     //persist and stuf.//on success...this.render();
   }

   render: function() {
      button.removeClass("btn-danger").addClass("btn-success");
      $("#activation-dialog").modal("show");
   }
}

Post a Comment for "Listen For Changes Against An Object In An Array Without Nesting Event Listeners"