Thanks for the reply - Yeah, I meant stopPropagation(), apologies.  If I
understand you correctly, you're saying that because events go through a
top-down (parent-to-child) capture phase before they bubble up, it would be
possible for someone to mistakenly add a capture-phase listener to the
event.  I'd have to agree that if you use common event names like "click"
for your custom events you'd be likely to run into trouble.  To avoid these
cases, it might be helpful to create a static constant for the event type,
where the constant can be named something 'normal' but its string value can
be more unique:

public static const CLICK:String = "mySpecialComboBoxClick";

Of course, then you'd basically be asking folks to only add listeners for
the event by passing your developer-friendly static constant as the event
type: the string itself would be too unwieldy.  And you'd also be weighing
the possibility that someone else happens to create a custom event type
using the same cryptic string.  Come to think of it, that whole scenario
seems a little weird, and doesn't offer a 100% foolproof resolution to the
problem.  If there's another way around this, I'd love to hear it (and don't
say "don't use custom events" ;) ).  Surely there must be a way to
definitively preclude the possibility of event type naming conflicts.

BTW, what are some other use-cases for capture-phase event listeners?  So
far I have placed them in the "things that can be done, but should be
generally avoided" category.

Thanks for the discussion 

-tom



-----Original Message-----
From: [email protected] [mailto:[EMAIL PROTECTED] On
Behalf Of Peter Hall
Sent: Sunday, September 03, 2006 12:34 PM
To: [email protected]
Subject: Re: [flexcoders] Re: Bubbling, Practical Use?

> "Any object listening for the event on the parent would also
> be notified by the event from the child. Bubbling events affect every
> parent of the event source, right up to the SWF root, so it's pretty
> much just as bad as using a root reference to store arbitrary
> properties and methods."
>
> Isn't that what the "cancelable" property is for?  You can (and maybe
> should) cancel the event at the last place you really need to listen for
it.
>

No. Cancelable is connected with preventDefault(), which prevents a
default action from occuring when the event occurs. For example a
component might automatically show an alert box when it dispatches a
"status" event - but a handler might present the error in a different
way, and call preventDefault() to stop the built-in alert from
showing.

You are probably thinking of stopPropagation(). This will prevent an
event from bubbling past a certain point. However, you cannot do
anything about the capture phase; a bubbling event will always trigger
at the root and every parent in between before the target is even
reached. If you were to call stopPropagation() at that point then
nothing could listen for your event. (This exact technique is used
with mouse events to prevent forms from being clickable, to implement
modal windows).

> The ComboBox-as-ItemRenderer scenario is a good real-life application for
> custom events.  Suppose I have a custom component which is based on the
> DataGrid.  I want to keep an array of all the selected checkboxes in my
> DataGrid, so that I can access it later via
myComponent.selectedCheckBoxes.
> When a ComboBox is selected, its reference will be put in the array. IMHO,
> it would be poor architecture to have each ComboBox target its
> parentDocument and put a reference to itself in that array.  What if you
> want to nest the ComboBox more deeply at some point down the line?  You
have
> to change that parentDocument reference.  With a custom event, you won't
> have to change anything, because it just bubbles up.

The point of the cellrenderer architecture is to provide a solid
framework, together with application-specific extension points. In
your example, you extend DataGrid and create cellRenderers, which
compose a ComboBox. By the very nature of the fact that the cellRender
implements the cellrenderer interface, it knows its context and how it
is being used, so there is a dependency. It is perfectly ok for this
renderer to know that it is part of your specially extended DataGrid,
and to use its methods. Alternatively, your extended DataGrid might
know that it uses this custom cellrenderer and can coerce the type, in
order to use its methods and listen to its events. In fact, depending
on your needs, I would suggest one of these options is the "best"(tm)
way.

When considering architectural approaches, it is important to
understand the dependencies in your code. Dependencies must exist, but
they affect the way that code is reused, so your dependencies must
reflect how you intend to reuse the code in the future. A common
architectural blunder is to attempt to remove ALL dependencies, which
results in very confusing code. In this example, we are saying that
our cellRenderer is dependent on your special DataGrid, and is
intended to be used in conjunction with it. Having a transparent
compile-time dependency, via a class import, is far more
understandable than to have a run-time dependency, based on throwing
an event into the aether, and trusting it will be caught by the right
receiver. In truth, by making this assumption, you have the same class
dependency, but without the transparency.


> Custom events also have the advantage that they are not broadcast by
default
> from every component in your structure, which makes it easy to listen for
an
> event from a particular component.  In the above scenario, you can't just
> listen for "click" events: what if there's something else in there that
can
> dispatch a "click"?  You'd end up having to filter by event.target to see
> whether your ComboBox was the dispatcher.  Instead, just dispatch a custom
> event from the ComboBox and listen for that custom event.
>
> Custom events can also contain any custom properties or data you would
like
> to pass along, which can simplify the listening code greatly.


You do not need to sell me on the concept of custom events! :-)
Custom events are absolutely fundamental to any Flex application. I am
not even suggesting that custom bubbling events are fundamentally bad.
I am saying that there are inherent risks with them, and that there
are very few reasonable applications for them, where a different
architecture couldn't solve the same problem. Most of the time that
I've seen them used, it has been to cut a corner, and has resulted in
less understandable code on a par with Cairngorm's global
EventBroadcaster. This type of code forces you into run-time debugging
far more often than when your code uses carefully considered explicit
dependencies.


> Worried about name collisions?  You can name your custom event anything
you
> like - obviously you need some sort of strategy for that, but a quick pass
> through your class library should show you what names are already in use.


You *could* use whatever name you like... But there is a lot of
benefit to concise, semantic event names, that are consisent with
other standard components. Conventions make components easier to use
and understand. Once you know that a component works "just like all
the others", you don't have to consult its documentation very much at
all.

Peter


--
Flexcoders Mailing List
FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt
Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com 
Yahoo! Groups Links



 





--
Flexcoders Mailing List
FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt
Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/flexcoders/

<*> To unsubscribe from this group, send an email to:
    [EMAIL PROTECTED]

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 


Reply via email to