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
Related
I want to know if its a good idea to have an mxml file for each component, then inline these various components in one mxml file and able to communicate between these mxml files ?
For example I have a overView.mxml and in this, i inline the other mxml files which contains components like datagrid, another mxml contains may be a form. Will i be able to communicate to the grid data by accessing its id in the form mxml ?
Please let me know if my question is not clear. I will try to rephrase it.
Thanks so much.
Yes, this is a good idea. It's much better than creating one giant MXML or class that contains all of your functionality.
At the same time, it caries some overhead. To communicate between the classes (MXML files are just classes) you have to dispatch events. A parent component that contains child components, can set public properties of its child components (with or without data binding).
You should try to decouple your components as much as possible. Try not to write code where the child component is explicitly referring to the parent (ie: try not to use the parent property). Instead dispatch an event from the child component and make the parent listen for the event.
Regarding your example with a data grid and a form:
If these two objects will have a lot of interaction between them, it will be much easier to keep them in the same MXML file. This doesn't sound like a scenario where one is a parent component that contains a child component. Since these "siblings" are likely to communicate w/each other, it would be easier to have them in the same MXML file. However, if things get complex and the file grows to more than a couple hundred lines, you will likely benefit from separating them.
Let's say you plan to use the form component elsewhere in your project w/out the data grid, then it also makes sense to separate them.
Regarding your question: "will the form component be able to communicate w/the grid component by accessing it's id?":
Technically, yes, you could do that but only by tightly coupling your form component w/the grid component. The form component can use the parent property to go up one level and use the id of the grid. But since the parent property is typed as a DisplayObjectContainer you have to fool the compiler and you loose the benefits of strong typing (because the DisplayObjectContainer doesn't have a property that is the ID of your grid). So while this is possible, it's not good design and prevents you from reusing the form component elsewhere.
This tight coupling defeats the purpose of creating separate components. So you're back to either facilitating that communication through dispatching events, or putting the grid and form in the same document :)
TLDR:
You should generally be trying to create re-usable components. So I would generally lean in that direction. MXML files are just classes, all the usual things people talk about in object oriented programming apply.
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.
I'm refactoring some Flex code written by another developer and I'm implementing a PresentationModel approach, as I like to separate out the ActionScript from the MXML. One of the problems I've found is that the original ActionScript code adds/removes elements from the MXML.
What happens is the handler function checks the model and if the values are correct will either create or remove a element from the view. What is the best way to get the presentation model to ad elements to the view and still keep this loose coupling that I'm aiming for.
I was thinking of using simple events which the presentation model dispatches and a view can list for passing the details of the element to add. Is there another solution?
Thanks
Stephen
If you're using the presentation model, I'd assume that you have some kind of data of what needs to happen. When items of any sort are being dynamically added/removed, I make sure to make it data-driven for easier manipulation. If you want another item added, add another data model to your dataProvider of choice (List, ComboBox, DataGroup, etc).
By doing this approach, you're abstracting the logic from the presenter to the view. Events should only be used as a way for your view to know when your presenter has accomplished something. Data can be received this way (and it's good practice to do so) OR you can just bind the data within the presenter to your dataProvider. Both are good, I just find binding to be cleaner and simpler.
Every part of code that do some graphical stuff (drawing border, setting style, drag & drop management, animations, ...), should be included in the view, not the presentation model.
For this kind of graphical that stuff should be executed after a property has been changed in the PM, we use the Cairngorm 3 Observer lib. Basically, it listens to some changes in the presentation model and allows you to execute a function in the View.
<cg:ObserveValue
source="{ model.firstName }" value="{ Name.SARA }"
handler="runEffectFunction"/>
See the documentation
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.
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.