How do I manage mediators for Parent-Child views?
I'm playing around with RL2 and looking at how to setup parent-child views and have a noob question...
In flash IDE I have a Gameboard MC in which I've dragged a Counter MC. In this counter I have a textfield with instance name "myText"
The gameboard and counter both have mediators - I'm not sure how I reference the TextField - for eg. do I need to listen for when the textfield is added to the stage in the Counter Mediator or can I access this via contextView?
Is there a special practice for dealing with Parent-Child views..or does each view simply get its own mediator?
Thanks!
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
Support Staff 1 Posted by Ondina D.F. on 27 Jun, 2013 07:50 AM
Hi Mike,
Not sure if I understand your question correctly. Would you care to elaborate on that?
If you mapped your views to mediators like so:
The GameBoardMediator and CounterMediator will be automatically created after the views have been added to the stage.
If you want to access the text field within your CounterMediator, you do:
view.myTextField.text =“some value“;
The GameBoarderMediator should not be allowed to have direct access to subcomponents of its view (GameBoarderView), like this: view.counterView.myTextField.
Instead, GameBoarderMediator should call a method (public API) on its view:
view.doSomethingWithTheSubView(someProperty);
And in GameBoarderView:
But, since both views are mediated, they should communicate with each other through their mediators, via events. If myTextField has changed, CounterView dispatches an event, and CounterMediator,which is listening to that event redispatches it. GamesBoarderMediator, or any other actor in your app that registered an event listener, can react to it, if need be.
If components weren’t mediated, an easy to remember rule is:
[ Parent->FirstChild.someMethod()->SecondChild.anotherMethod() ]
[ Child.dispatchEvent(some event)->Parent listens->Parent handles event ]
It is not clear to me what you mean by:
Why do you need the contextView to access myTextField?
If you want to access something from the contextView, you need to do this:
contextView.view.someProperty
or
contextView.view.someMethod(),
where view is the actual display object.
Ondina
2 Posted by mike on 27 Jun, 2013 11:56 AM
Hi Ondina,
Fantastic answer :) That's cleared up a lot of things for me. If I may
impose a bit more I have this set in the Counter Mediator
public function CounterMediator()
{
view.textField.text ="some value";
}
I imported a swc from Flash, with automatically declare stage instances
ticked - yet the field is still empty. Can you see what I may have missed?
Thanks again for your info
Cheers
Michael
Support Staff 3 Posted by Shaun Smith on 27 Jun, 2013 12:22 PM
Hi Michael,
You need to wait until the Mediator has been registered before attempting to access the injected view. You can do this by overriding the
initialize()
method:Hope that helps!
4 Posted by Mike Wheelaghan on 27 Jun, 2013 01:02 PM
Hi Shaun many thanks for your reply !
If I add a counter separately to the contextView eg
var gb:Gameboard = new Gameboard();
var counter:Counter = new Counter();
contextView.view.addChild(gb);
contextView.view.addChild(counter);
The CounterMediator fires and sets the text fine. What I would like is to preserve the design of the Gameboard in which this Movie Clip contains a Counter symbol at a particular x, y. I have an Counter MovieClip named "myCounter" in the fla file
Then I try something like this in GameboardMediator - do you know if this is possible the way I describe?
override public function initialize():void
{
view.myCounter.setText("testtset");
}
Thanks again :)
Mike
Support Staff 5 Posted by Shaun Smith on 27 Jun, 2013 01:15 PM
Hiya,
You don't need to add them to the ContextView separately in order for them to be mediated. Robotlegs will pick up on any views that you have mapped when they land on stage. In other words, if Gameboard contains an instance of Counter, you can just add a Gameboard to the stage. Usually, you only interact with the ContextView at startup, where you add a single "main view" to the stage, any sub views that have been mapped will be picked up and mediated. Let me know if that clears things up a bit.
6 Posted by Mike Wheelaghan on 27 Jun, 2013 02:07 PM
Thanks a lot for that Shaun and Ondina - managed to get it working with your help
Cheers!
Mike
Support Staff 7 Posted by Ondina D.F. on 27 Jun, 2013 02:26 PM
Mike, the pleasure is ours :) Good to hear you got it working!
You can re-open this discussion, if you get stuck again and/or open new discussions for new issues.
See you around,
Ondina
Ondina D.F. closed this discussion on 27 Jun, 2013 02:26 PM.
mike re-opened this discussion on 28 Jun, 2013 10:08 AM
8 Posted by mike on 28 Jun, 2013 10:08 AM
Hi Guys, if I may just add one more question - I've noticed the CounterMediator doesn't seem to activate when its an instance variable inside Gameboard, but does if I add separately to the ContextView. If I understand Shaun's notes correctly this myCounter instance variable inside Gameboard would startup its own CounterMediator?
thanks so much for all your help so far :)
M
Support Staff 9 Posted by Ondina D.F. on 28 Jun, 2013 12:30 PM
Hi Mike,
You have to create an instance of CounterView and then add it to GameboardView.
In GameboardView:
After counterView is added to the stage, its mediator will be created automatically.Is your project a pure as3 one or Flex? How are you initializing your context?
Could you attach a sample app? I’m willing to take a look at it and tell you how to add your views and so on. It might be easier to see why it is not working for you.
Ondina
10 Posted by Mike Wheelaghan on 28 Jun, 2013 02:08 PM
Thanks again Ondina ! Here's my effort so far - Im attempting to preserve the flash ide design, so in case I have a designer draw a gameboard with a counter at a specific location and several other movie clips in flash - that if I reference them by name I can preserve their position in the scene (otherwise if I addChild() I would need explicitly set x, y..or am I mixed up about that?)
cheers :)
Support Staff 11 Posted by Ondina D.F. on 28 Jun, 2013 02:56 PM
I've dl-ed it. I'll be back...
Support Staff 12 Posted by Ondina D.F. on 28 Jun, 2013 03:20 PM
Here the changes:
TextX.as:
Note the line .afterInitializing(init).
AppConfig:
CounterMediator
Something is wrong with _myTf, but I can’t see the base classes, so I don’t know exactly why myTf is not working. Thus I created another TextInput in the constructor of the Counter:
Gameboard
It’s working fine so far:)
It would be good if I could see the base classes as well.
I’ll attach the changed project later on.
Support Staff 13 Posted by Ondina D.F. on 28 Jun, 2013 03:36 PM
I forgot to say that I used robotlegs-framework-v2.0.0 in your project.
(http://www.robotlegs.org/)
Support Staff 14 Posted by Ondina D.F. on 28 Jun, 2013 04:27 PM
Ok, it works with the base text field as well. I didn’t see it, because Counter was not fully on screen.
So, var c:Counter = new Counter(); c.x=150; addChild(c);
solves the problem, haha.
Then you can set the text like this:
In Gameboard (it should implement an interface having setText):
In Counter
The names of the text fields are kind of confusing :)
I’m attaching the project with my changes.
Support Staff 15 Posted by Ondina D.F. on 28 Jun, 2013 04:39 PM
Hmm, I don’t know how to answer that.
If you set Counter’s position, size etc inside Counter’s constructor, they are preserved when you add it in Gameboard, and of course you don’t need to set them again in Gameboard. But, I’m afraid I don’t understand what you mean :)
Support Staff 16 Posted by Shaun Smith on 28 Jun, 2013 04:50 PM
I haven't had a chance to look at the sample yet, but this is my understanding:
This is basically what RL was designed for. I'm not sure why it isn't working for you, but it really should. It would suck to have to lay everything out with code!
I can't look into it right now (I'm still at work), but here are some things to double check:
Will try to take a look later / over the weekend.
17 Posted by Mike Wheelaghan on 29 Jun, 2013 05:39 AM
Hi - many thanks again guys for all your patience :-)
Shaun is exactly right - that's what I'm trying to achieve. Have Flash IDE to design a composite nested view and map separate mediators to individual instances within that view.
Ondina thanks very much for your example I can see now that using addChild() is a guarenteed way to activate the child mediator (Counter) . My eventual goal is what Shaun describes ie.
The package.GameboardBase and package.CounterBase are the linkage names I provided in the Export settings in Flash IDE so all the code is in flashbuilder. I export a single swc and import into FB
Where I'm trying to get to is
viewProcessorMap.map(ICounter).toProcess(new MediatorCreator(CounterMediator));
viewProcessorMap.map(IGameboard).toProcess(new MediatorCreator(GameboardMediator));
var gb:Gameboard = new Gameboard();
contextView.view.addChild(gb);
Since Gameboard contains a reference to Counter via
public function get _myTf():Counter
{
return this["myCounter"]; //myCounter is the name of the Counter Symbol that is placed inside the Gameboard Symbol
}
and we can set the text of the Counter via the GameboardMediator, I'm hoping it's possible to have this instance of Counter mediated. (which has specific layout and keyframe location within the Gameboard Movie Clip )
The reason for all this is that it would achieve a clean separation between designer and developer and no matter how complex the nested/composite view gets - you can have as many sub-views as you like , each view is mediated and logical separate from the parent.
Hope to get your thoughts on this - appreciate the sample code again
M
Support Staff 18 Posted by Ondina D.F. on 29 Jun, 2013 09:16 AM
Well, Shaun seems to have understood better what you need to achieve :)
Yes, I could see CounterBase and GameboardBase in the referenced libraries. CounterBase has a property textField:TextInput and GameboardBase has myCounter:CounterBase.
My confusion was about your interfaces and the way you’ve mapped them. It wasn’t clear what exactly needed mediation.
CounterBase and GameboardBase don’t implement any interfaces, so the mapping to ICounter won’t work, unless you add the view implementing ICounter to the stage.
Of course you don’t need to add the CounterBase again, if it was already added by Gameboard, but if you have these mappings:
and you add gameboard like this
and you don’t add Counter too, only GameboardMediator will be created.
If you map them like this:
and in CounterMediator you inject CounterBase, both mediators get created, and you don’t need to add Counter manually. That means, that the mediator for a subcomponent from your swc will be created, if it is mapped correctly.
I think you need to let CounterBase implement ICounter if you want to keep your original mappings.
Maybe I’m wrong, though.
19 Posted by mike on 29 Jun, 2013 09:55 AM
Thanks Ondina that really helped. If I use CounterBase that works , I can access the textfields directly from both mediators - In practice I will have a CounterUpdate command sending to a CounterMediator and so forth...I definitely need to think more about the view architecture but at least I know that it can be done no worries, thanks heaps for helping me out !!
M
Support Staff 20 Posted by Ondina D.F. on 30 Jun, 2013 06:46 AM
It's nothing!
Ondina D.F. closed this discussion on 09 Jul, 2013 01:44 PM.