Reputation: 13881
I have a Backbone view (InnerView
) that is rendered inside of another view (OuterView
). Both contain event handlers for the click
event, and event delegation is enabled (by default).
I would like InnerView
to append some data to the event before it propagates further. However, the code — as presented below — doesn't seem to affect e.data
at all, as it remains undefined afterwards:
var InnerView = Backbone.View.extend({
events: {
"click": "onClick"
},
render: function () {
// ...
},
onClick: function (e) {
e.data = e.data || {};
e.data.myData = 123;
console.log(e.data); // Object { myData: 123 }
}
});
var OuterView = Backbone.View.extend({
events: {
"click": "onClick"
},
render: function () {
// ...
this.$el.append(new InnerView);
// ...
},
onClick: function (e) {
console.log(e.data); // undefined
}
});
I tried stopping the event from propagating and then retriggering it with custom data (which would be stored in a somewhat different format, as I can't see a way to append data to the event object here):
// alternative version of InnerView#onClick()
onClick: function (e) {
e.stopImmediatePropagation();
this.trigger('click', {myData: 123});
}
But then OuterView
received no click event at all.
How do I deal with this problem? Note that I cannot trigger my event directly (or call a method, or set a property) on the destination view, as the two aren't exposed to each other (and that is why I've decided to utilize the event mechanism).
Upvotes: 0
Views: 472
Reputation: 658
One way of achieving this is to create a globally accessible object of timestamps (event.timeStamp) containing data. You can attach an object to that array - for example:
var eventTimestamps = {}
function someEventCallBack(e) {
if (eventTimestamps[e.timeStamp] === undefined) {
// it's a new event, attach things?
eventTimestamps[e.timeStamp] = { name: 'Bob' }
} else {
eventData = eventTimestamps[e.timeStamp]
// this event has data
if (eventData.bob !== undefined && typeof eventData.bob === 'string') {
console.log("my name is..." + bob)
}
}
}
The above is rather clunky. I've created this codepen which reduces all this functionality into an easy-to-use object with no type guarding in the example just so the logic behind it is clearer.
https://codepen.io/petermakeswebsites/pen/abwJxvK
Upvotes: 0
Reputation: 8993
You can't use this.trigger()
because this is using Backbone's Events API and not jQuery's. You would need OuterView to listen for this event from InnerView, but, as you said, the views are not exposed to each other.
If you want to send data up the DOM, I think you are on the right track in turning to jQuery's trigger. However, I would trigger a custom event from InnerView:
onClick: function () {
this.$el.trigger('custom', {
myData: 123
});
}
This way, the click event propagation can proceed as normal and OuterView can listen specifically for the custom event:
events: {
"custom": "onCustom"
},
onCustom: function (e, data) {
console.log(data.myData); //123
}
Additionally, note the convenience of having your custom data passed as the second parameter to the event handler.
Upvotes: 1