Dispatch event to popupmanager without reference to instance - apache-flex

I'm fairly experienced with Flex 4, but I still haven't needed frameworks yet (I like to do everything myself) and don't want to use them either, I know it's advantages and have learned how to use one of them, but still, no.
How can I dispatch an event in the main application and have a component inside a popupmanager to react to that event? All this dispatching the event within the main app and NOT aiming it to the popupmanager or the component instance, I want to be able to fire the event and not care about who gets it or if anyone reacts to it at all so if that is possible then I wouldn't care about keeping track of said popups.
I already dispatch an event from the component and receive it in the main application by bubbling the event and therefore being agnostic of each other, now I want it backwards.
Note: I have used singletons, but it's not the approach I need this time.

It sounds to me you are in desperate need of RobotLegs, you seem to be asking how to to create/use an event bus system in order to de-couple your components which is exactly what robotlegs is amazing at.
One thing you should definitely also look at is ActionScript 3 Signals. Signals is an approach to make strongly typed events like .NET Framework, instead of the magic strings event system, and is a fantastic easy bolt on addition to any Flash/Flex project.
Another way that is common is a mediator/controller singleton pattern. Let's say this is an automotive application, and we have a service layer that behind the scenes is receiving some data from the server, whilst at the same time our popup is behind displayed. One way we solve this problem is create a singleton based controller for our data like PartsController. It also has some public const Signals like SingalDataUpdated. The popup can now do something like PartsController.SignalDataUpdated.add(OnPartsUpdated). OnPartsUpdated is a local method inside the popup that can now react to the event as necessary and has no coupling to any other UI component. This is typically the approach we take and ensure that no UI component has explicit knowledge of any other UI component, and instead only talk to the controllers. One thing you need to ensure though is when the popup is closed remove the signal lister.
Again though, RobotLegs does most of all these for you and encourages some very great architecural best-pracitces. I would highly recommend you read through their documenation and get familiar with it. It will change your life when you realize how modular and maintainable it helps make your code.
Good luck!
Update regarding context and singletons
The idea regarding a context is to create a single singleton known as your application's context that stores the instances of what would be your other singletons. Inversion of control (IoC) and RobotLegs just wires things together so it dosen't look like absolute crap to work with, but you can just use a simple IoC injector like Swiz or SwiftSuspenders which RobotLegs is built upon. So, for example, you might hit a particular controller like:
AppContext.Instance.ProductController.SignalProductAdded.add(OnProductAdded);
But that is a bit ridiculous to try to access everything this way. Here comes RobotLegs to the rescue. Instead define injection rules in your RobotLegs context, so if a component asks for a UserController via an inject metadata tag, everything would get the same UserController. Exactly like a singleton, but correctly so in your component define;
[Inject] public var _objProductController:ProductController;
Now your component can work with the controller object as if it was its own, but instead it was injected in by RobotLegs on construction. For me and and most of my products I build a few base objects like GroupBase, PanelBase, PopupPanelBase, etc. that extend the proper component and already have all the controller injection properties so any component derived from these already connect to the proper controllers as needed.
For your simple project, it's like easier to roll your own and just create a single singleton for your context to hold your controllers and communicate with application's context that way. These are all pretty high level architecural decisions and everyone works differently at this level based on their experience, preference, or whatever. The most important thing is that it works for you, and you are comfortable with the architecture. RobotLegs helps make everything very decoupled which has some amazing unforseen benefits later.
Good luck!

If I understand the question:
how can I dispatch an event in the
main application and have a component
inside a popupmanager to react to that
event
Inside your pop up component, you can do something like this:
var app:Application = FlexGlobals.topLevelApplication as Application;
app.addEventListener('myCustomEvent',onMyCustomEvent);
Now any instances of the myCustomEvent that are dispatched by the main Application class will fire the handler in the popup. Also, any instance of the myCustomEvent that bubble up to to the main Application class will fire the handler in the popup.
I'm not sure if this is a good idea. Accessing the topLevelApplication will add external dependencies to your pop up which may reduce re-use of said component in the long term. Accessing the topLevelApplication is not a decision I would take on without thought.
If you were trying to ask a different question; it is unclear to me from your post, which I found kind of confusing.

Looking further into what Flextras.com said (Jeffry Houser I presume), this feat is impossible, events never bubble to children, only to parents.
Therefore, this has to be done in a central event repository approach, which is the way frameworks do it mostly.
This is indeed one of the problems solved by dependencies injection found in some frameworks as robotlegs.

Related

Flex Cairngorm 3 Presentation Model Initializations

ok so I have a TitleWindow that I open up... and I have 6 states defined. I am using the Presentation model pattern for all of my views. I have discovered a frustrating nuance. When I tell my window to go to XXX state, the controls have to initialize since the states in flex use lazy loading. so... my PM code that says myTextArea.text bombs out and say "cannot access..." so as a work around, I made some creationComplete events on my controls to register the control with the PM. So when the state changes, the textarea finally initializes and on creationComplete calls PM.registerTextArea() which sets a reference to it. then in that function I run my code... myTextArea.text.. etc.
This seems like such a ugly hack that I hate it. Is there any way to wait until the entire state in created then call code on the PM? I have tried enterstate... but this event seems to fire before the state controls are ready.
I tried to add a comment, but I guess editing is the only way I can do this...
to everyone: thanks for the great feedback. I am doing something slightly off straight PM. Every view has a viewController (as I call them). Its kinda my own hybrid of a delegate / dataprovider. But this is moot. It's the flex component lifecycle when dealing with states that is the pain. if you change state.. there is no event to say "all my components in this state are ready". only event to say "we changed state". so my code that fires on state change is trying to talk to components that aren't ready yet. So from what I see, there seems to be no design pattern or perfect way to ensure that all components are created in a state unless using creationComplete on every component in the state to register it is ready... if you don't, you get a race condition. Regardless of frameworks or design patterns, this seems to be a root issue.
The textarea is an easy PM fix.. just bind it to the pm value. But there are other times I can't.
Specifically, I am trying to attach video to a display once I get to that state. This is done via addchild. regardless of where I do it.. I need to know that the videoDisplay is done loading before I call addchild. I even tried currentStateChange event since docs say that fires last... but alas.. the components in the state are still initializing. So it seems that creationComplete is my only option. Maybe the only sane way to keep to clean code is to create the entire thing (videodisplay and video) using as once the state is entered. I just hoped the flex framework had events to ehlp me here rather than buiilding everything on the fly in as.
Since your PM has a reference to a visual component (myTextArea), this isn't a completely pure form of a presentation model. It appears to be more of a supervising presenter / controller type of setup.
That being said, the way I would fix your problem would be to use a complete presenter outright ( no knowlege of the view at all ) or use a complete controller ( view implements an interface through which the controller communicates ). The advantage of using a presenter in Flex is that you can create a bindable value such as text or selectedItem, and the view will bind to that variable whenever it comes online so the issues dealing with the lifecycle of Flex components go away.

What's the Flash equivalent of FlexEvent.CREATION_COMPLETE

I'm moving some Flex classes to pure Flash/AS3 to be part of a shared library. I have an event listener on FlexEvent.CREATION_COMPLETE to create and add display-objects once things are running, but I don't know the right way to do this in Flash?
edit: Maybe if my class subclasses Sprite rather than a Flex class, I can add children in the constructor, I don't need to wait for a "construction complete" event?
It depends on what you are trying to do: When you add children in the constructor, you will not be able to depend on any information about the stage and/or other elements on it. I have found it a better practice to add an event listener for Event.ADDED_TO_STAGE in the constructor, and have the handler method initialize the element.
You're really comparing apples and oranges here.
The Flex Framework is a UI Framework, and the CREATION_COMPLETE event is part of that framework.
Flash Professional is an IDE, primarily geared for creating animation. It has ActionScript support, but is not a framework and does not offer anything beyond native ActionScript other than libraries or classes you build, buy, create, or borrow.
If you want some parallel to creationComplete, you'll probably need to find--or create--a UI Framework. It is, in theory, possible (although not easy, nor something I'd recommend) to initialize the Flex Framework for use inside a Flash IDE created movie. After all, under the hood it is all ActionScript.
creationComplete Dispatched when the component, and all of its child components, and all of their children, and so on have been created, laid out, and are visible.
See more info on the flex life-cycle events and some that are plain flash here: also +1ed the added_to_stage as it's likely what you'll need in this case.
http://livedocs.adobe.com/flex/3/html/help.html?content=containers_intro_3.html

Flex, RobotLegs: must you mediate all child components of a visual component?

In the examples for RobotLegs, it appears that mediators are used on every button/textArea, rather than on the custom component that contains these children. This would be very time consuming would it not?
From Joel Hooks InsideRia Example
Dependency injection works better with
unambiguous classes. What this means
is that by extending TextArea into our
new MessageView class, we are creating
a specific view component for the
dependency injection to act upon. This
is important if our application were
to have several TextAreas that served
different purposes. By dividing up our
classes in this way, we are clearly
defining the intent of the class and
allowing for the dependency injection
tools to do their jobs effectively.
No, don't mediate every child component. Your components should be organized into groups that perform related actions. In the examples the components are extremely simple and do not reflect what a real application would look like.
One rule of thumbs I use is thinking if that component needs any communication with the rest of the application, or if its only a part of a whole. Keep in mind that mediator are only intended to serve as a bridge between the view and the app.
For example, if I've a view with a form (asume a login form) I don't mediate all the child components (the textfields, the buttons, etc.) because it would be pointless and would have a proliferation of classes and objects on runtime. When I do the form I think, what does the view by its own? and what the other parts of the app should do with it?
When the user fills the form and clicks a button, the view dispatches an event (LoginRequestEvent, for this case), and then the mediator should redispatch that event, making the mediator very lean.
But with practice of the framework, you'll come up with this feel of what you shold mediate. For instance, in one app I mediate every item renderer of a list, and on other I mediate a view stack with two or three navigation contents.
Hope it helps

Get all event listeners on a specific component

I have an application in flex, it has some components out of the box and quite a few of custom components and events.
I want to get all event listeners on a specific component in runtime, I know how to do it with monkey-patching the framework but I do not want to use a monkey patch nor can I rely on this in production.
Is there a way?
The EventDispatcher has a pretty slim public interface:
addEventListener
dispatchEvent
hasEventListener
removeEventListener
willTrigger
This means the list of listeners isn't exposed. You can only tell if there is at least one event listener for a particular type of event.
I would re-examine why you need to do what you want to do. In a typical Observer Pattern the listener list isn't meant to be exposed. I have a strong feeling if you are trying to get that list then you are approaching a higher level problem from the wrong direction.
You can't. You could simply use custom components only and override addEventListener to gather the information. I don't really see why monkey patching wouldn't work. Flex is powerful in features but poor in design and I guess you'll have to just live with that.

Can I make my MXML Component a Singleton?

I have an MXML component in a website that I am reusing in a few different screens.
Based on what the user clicks, the component initializes a few values and starts playing media.
Now if I click through the site, and I play media in screen 1, the component initializes fine and plays the media.
If I then go to screen 2 and play the media, the component initializes twice. Once for screen one, and once for screen 2.
When I then go to screen three, it will start initializing three times.. So it is creating a new instance of the MXML component for each screen!!
How can I make sure that the MXML component only initializes for the screen that I need it to initialize for?
What I really want is that this component always has just one instance throughout the whole application. Is it possible to make that MXML component into a Singleton, so that I always have one instance of that MXML in my application?
Can you explain this a little more indepth? What do you mean by "screens"? It sounds like you have your component nested in some sort of view stack, and that your screens are different sections in the view stack, but it's hard to tell here.
Regardless, I think the solution is to abstract the part of your component that you want to be a singleton from the view. Flex initializes objects in view stacks in a lazy manner by default, but this can be overridden using the creationPolicy property on the ViewStack object. It sounds like your creationPolicy is initializing children as you access them, and something in your component code is causing other instances of the same object to re-fire some initialization code when others are created (possibly in your experimenting for an MXML singleton.)
To truly achieve your desired effect, you should probably just write a bit of actionscript that intelligently re-parents the display object you only want to be created twice. The idea of a "singleton" doesn't make as much sense when we're talking about view objects on screens - to have it displayed in many places, you need many instances, and the process of re-parenting is slightly more complicated than the singleton pattern, so you'll need to do a bit of creative logic around that.
Hope this helps - again, please feel free to post some more source code if you want a more specific response.
Why don't you make the component into a module and use it that way. You Load and/or Unload a module and use it where ever you like! in just calling it as a single item! and you have very much less overheads in your application.

Resources