Flex Popups - getting the parent view
I'm looking at this KB article, which talks about how to mediate
a Flex Popup:
http://knowledge.robotlegs.org/faqs/reference-mvcs-implementation/h...
That's helpful, but I have a question. In the command class, it has a reference to the context view (the variable is called contextView). Presumably that object is injected into the command, so it's declared something like this:
[Inject] public var contextView:ContextView;
My question is, how do I set up the injection mapping for that view?
One idea I have is to use injector.mapSingleton(ContextView), but I'm concerned because the ContextView class is already mapped for injection via MediatorMap:
mediatorMap.mapView(ContextView, ContextViewMediator);
Is mapSingleton() the right approach anyway? Other suggestions?
(I also considered passing it as a property of the event that triggers the command, but that just means that I'll need to get it into the command somehow, either by creating the event in the mediator for the view, or by somehow injecting it into the event. But the command isn't really related to/triggered by anything in that mediator, so that just seems like moving the problem to a different place rather than actually solving it.)
Thanks,
Paul
Comments are currently closed for this discussion. You can start a new one.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
1 Posted by Paul Robertson on Dec 18, 2009 @ 05:41 AM
Update:
I tried using mapSingleton(), and while I do get an instance of ContextView, it's not (as far as I can tell) the same instance as the actual one.
Likewise, without using mapSingleton(), I still get a ContextView instance injected (contextView isn't null). However, again, as far as I can tell it's not the same as the real ContextView.
(The way I'm trying to test if it's the real ContextView is that in the command's execute() method I write some text into a TextInput control in the context view, using contextView.testInput.text = "Hello"; but nothing shows up in the TextInput control. So it could just be an error in my testing methodology as well.)
2 Posted by Paul Robertson on Dec 18, 2009 @ 05:49 AM
Update 2:
Oops, disregard the second paragraph in my "Update" number 1 above. When I removed mapSingleton() the app didn't recompile before I ran it. It turns out that without mapSingleton(), SwiftSuspenders throws an error telling me it doesn't know how to map the injection. So that at least tells me that just having it mapped using MediatorMap isn't enough.
3 Posted by xisari on Dec 18, 2009 @ 09:37 AM
The injection mapping of contextView is done in RL's Context class. The value comes from the first parameter passed to its constructor. You don't need to map it manually.
So whatever DisplayObjectContainer you pass to the constructor of your context class, it will be available in every command via the injected contextView value.
Support Staff 4 Posted by Ondina D.F. on Dec 18, 2009 @ 10:30 AM
Hi Paul,
I’m not qualified to answer questions like this, but….
This works in a command:
var myContextView:Object=this.contextView;
myContextView.testInput.text = "Hello";
But it doesn’t work if myContextView ‘s data type is DisplayObjectContainer .
So contextView.testInput.text = "Hello"; won’t work.
Maybe because of this(?):
“The DisplayObjectContainer class is an abstract base class for all objects that can contain child objects. It cannot be instantiated directly; calling the new DisplayObjectContainer() constructor throws an ArgumentError exception.”
Ondina
Support Staff 5 Posted by Shaun Smith on Dec 18, 2009 @ 05:00 PM
Hi Paul,
Mediators and Commands in the MVCS implementation get injected with the contextView automatically - the contextView being the view instance that you handed to the context when you instantiated it.
The mapping for that injection happens in the context itself (in org.robotlegs.mvcs.Context):
And the injections are declared on the actors like so:
The contextView will always refer to the "root" node (so to speak) of the context, and shouldn't change at any point in the lifecycle of that context.
If you have a custom class (or an actor) that needs access to the context view, you can simply declare a dependency on it (just like Mediator and Command do) yourself:
Your intuition regarding the use of mapSingleton for the concrete class of a view component that has already been mapped in the MediatorMap is somewhat correct: The MediatorMap makes a temporary mapping for the view component just before it injects into a new mediator instance. That mapping gets deleted after the injection and would unfortunately flush out your own mapping - this is the tradeoff we must make to enable automatic mediation, and is regrettable, but presently unavoidable (until we come up with a better solution). However, I don't think that this aspect has much to do with your problem.
So, the contextView always refers to the root display object container for your context. A complication with Flex popups is that they are created on a separate display list - I assume that this is to enable that fancy blur effect that gets applied to the app when a modal popup appears. Essentially this means that, while a Flex Popup can be mediated perfectly adequately, we must be aware that our Popup live in a wholely different universe to the rest of our app. It's not so much a problem, as just something to be aware of.
I would like to find out more about what you are wanting to do. What is it that you need a reference to? And where do you need that reference?
6 Posted by Paul Robertson on Dec 18, 2009 @ 07:51 PM
Thanks xisari, Ondina, and Shaun. It turns out that the solution (that you pointed out) was much simpler than I expected.
I didn't notice that the Command class defines a contextView property. That gives me exactly what I need. (When I read the example in the page I referred to, I mistakenly assumed that the contextView variable was created through some injection that was omitted from the code.)
The reason it wasn't working for me was because of my own confusion. I won't bother trying to explain it -- it'll just further complicate things.
To answer your question Shaun, really what I was trying to do was just get an instance of a "root" or close-to-root display object so that within a command class I can call PopUpManager.createPopup() and have a display object to pass in as the first parameter. Since the Command class has the contextView property available, that works just fine for me.
Sorry about the confusion! Really the only suggestion I can offer is maybe a note in the article about mediating popups, mentioning that contextView in the command class is inherited from Command. But then again, I should probably pay more attention to the docs before I ask questions like this!
Support Staff 7 Posted by Shaun Smith on Dec 18, 2009 @ 08:06 PM
Haha! Yes, I often wonder how many things in Robotlegs seem more complex than they actually are. I've added a note to the bottom of:
http://knowledge.robotlegs.org/faqs/reference-mvcs-implementation/h...
Does it make sense as it's written?
8 Posted by Paul Robertson on Dec 18, 2009 @ 10:07 PM
Shaun,
That note makes sense to me.
The only thing I'd say is that it might be more useful to have a comment in the code itself, in addition to (or instead of) the note. (This past July we conducted some usability studies on the Adobe documentation, and found that many people completely ignore anything outside of code blocks.)
So maybe just something as simple as adding a comment to the end of this line:
PopUpManager.addPopUp( popup, contextView ); // contextView is defined in Command
In any case, thanks for all your help.
Shaun Smith closed this discussion on Dec 20, 2009 @ 10:53 AM.