Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Find Triggered Event From Backbone.listenTo?

In Backbone, I'm using the new Backbone.listenTo event. One of my instances has the listener attached to three different events e.g.:

this.listenTo(this._Collection, 'reset add change', this._setCollection);

It is called appropriately when it's supposed to and there are no issues there. What I don't know is how to find out which event was triggered. I have access to the e argument using:

_setCollection: function(e) {
    // Do fun stuff
}

The problem is that the e argument only sends a copy of the collection and doesn't mention what event is actually triggered. I've tried e.type and e.target but those objects don't exist. Here's a copy of the e object from Chrome Dev tools:

_byCid: Object
_byId: Object
_events: Object
    add: Array[1]
    change: Array[1]
    remove: Array[1]
    reset: Array[1]
__proto__: Object
_listenerId: "l16"
length: 3
models: Array[3]

How can I find what event was triggered?

EDIT: Answer Clarification: Although the marked answer is technically correct, as pointed out by mu_is_too_short the correct answer is using multiple handlers and not performing this type of "chicanery"

like image 519
Brandon Avatar asked Jan 10 '13 00:01

Brandon


1 Answers

You can't detect the event type directly but, in some cases, you can infer it from arguments. The events catalog has this to say:

  • "add" (model, collection, options) — when a model is added to a collection.
  • "reset" (collection, options) — when the collection's entire contents have been replaced.
  • "change" (model, options) — when a model's attributes have changed.

Lucky for you, all three of those events have different parameters so the contents of arguments will uniquely (in this case) determine the triggering event:

  1. If arguments[0] is a model and arguments[1] is a collection then you have an "add" event.
  2. If arguments[0] is a collection then you have a "reset" event.
  3. If arguments[0] is a model and arguments.length is 2 then you have a "change" event.

So you can do something unpleasant and fragile like this in your _setCollection:

    // M is your model, C is your collection.
    if(arguments[0] instanceof M
    && arguments[1] instanceof C) {
        // An "add" event...
    }
    else if(arguments[0] instanceof C) {
        // A "reset" event...
    }
    else if(arguments[0] instanceof M
         && arguments.length == 2) {
        // A "change" event...
    }
    else {
        console.log('confusion!');
    }

Demo: http://jsfiddle.net/ambiguous/Y9UUX/

I wouldn't recommend this sort of chicanery though, it is kludgey, fragile, and can break if you add more event types to the list. If your event handler needs to know what sort of event triggered it then you'd be better off using separate handlers for each event type: three functions and three listenTo calls are better than a small pile of ugly hackery.

like image 126
mu is too short Avatar answered Oct 04 '22 21:10

mu is too short