My view, TuneBook
, has several child views of type ClosedTune
. I also have separate full page views for each tune, OpenTune
. The same events are bound within ClosedTune
and OpenTune
, so I've designed my app so that they both inherit from a shared 'abstract' view Tune
.
To make my app more scaleable I would like the events for each ClosedTune
to be delegated to TuneBook
, but for maintainability I would like the same handlers (the ones stored in Tune
) to be used by TuneBook
(although they'd obviously need to be wrapped in some function).
The problem I have is, within TuneBook
, finding the correct ClosedTune
to call the handler on. What's a good way to architect this, or are there other good solutions for delegating events to a parent view?
Note - not a duplicate of Backbone View: Inherit and extend events from parent (which is about children inheriting from a parent class, whereas I'm asking about children which are child nodes of the parent in the DOM)
In your parent view (extending also from
Backbone.Events
), I would bindonEvent
to the DOM event. On trigger, it would fire a backbone event including some "id" attribute that your child views know (presumably some row id?).Child views would then naturally subscribe to the parent views event that concerns them. Below I do it in
initialize
passing the parent view as well as that special id attribute you used before inoptions
.You can of course also set up similar subscribers on
Tune
orOpenTune
.Great solution I have taken from this article (@dave-cadwallader comment).
Extend an general backbone events object and store it in a reference
vent
:Pass it to parent view:
The child view will trigger an event:
And the parent view is listening to the child event:
Disclaimer - pay attention that the
vent
object has to be injected to every view so you will find in this article better design patterns to make use of.Here are a couple of possibilities.
1. Centralized: store
ClosedTune
objects in theTuneBook
instanceStore a reference to each
ClosedTune
intune_book.tunes
. How you populatetune_book.tunes
is up to you; since you mentioned an adder method onTuneBook
, that's what I've illustrated below.In the
TuneBook
event handler, retrieve theClosedTune
fromtune_book.tunes
by using something like theid
attribute of the event target as the key. Then call theTune
orClosedTune
handler.http://jsfiddle.net/p5QMT/1/
2. Decentralized: associate the view object with the DOM object using
jQuery.data()
When you create a
ClosedTune
, store a reference to it, e.g.this.$el.data('view_object', this)
.In the event listener, retrieve the
ClosedTune
, e.g.$(event.target).data('view_object')
.You can use the same exact handler for
ClosedTune
(inTuneBook
) andOpenTune
, if you want.http://jsfiddle.net/jQZNF/1/
Response to comment
I guess it depends what kind of housekeeping / syncing you feel the need to do, and why.
Why do you feel that you "need to remove the view from tunebook's list of views"? (I'm not suggesting you shouldn't, just asking why you want to.) Since you do, how do you think @ggozad's approach differs in that respect?
Both techniques store
ClosedTune
objects in theTuneBook
instance. In @ggozad's technique it's just hidden behind an abstraction that perhaps makes it less obvious to you.In my example they're stored in a plain JS object (
tune_book.tunes
). In @ggozad's they're stored in the_callbacks
structure used byBackbone.Events
.Adding a
ClosedTune
:1.
2.
If you want to get rid of a
ClosedTune
(say you remove it from the document withtune.remove()
and you want the view object gone completely), using @ggozad's approach will leave an orphaned reference to theClosedTune
intune_book._callbacks
unless you perform the same kind of housekeeping that would make sense with the approach I suggested:1.
2.
The first line of each example is optional -- depending if you want to clean up the
ClosedTune
objects or not.Well, it ultimately comes down to your preference for how to structure things. If you prefer storing the view objects in a more centralized fashion, you can store them in the
TuneBook
instance instead of usingjQuery.data
. See #1: Centralized.One way or another you're storing references to the
ClosedTune
objects: usingjQuery.data
, or in a plain object in theTuneBook
, or in_callbacks
in theTuneBook
.If you like @ggozad's approach for reasons that you understand, go for it, but it's not magic. As it's presented here I'm not sure what advantage is supposed to be provided by the extra level of abstraction compared to the more straightforward version I present in #1. If there is some advantage, feel free to fill me in.