> "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 <*> 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/

