Modularity
Hi! I've got a problem:
I've got 2 contexts with same mediator-view mapping, the second context view lays inside the first. It looks like:
Container
|--ContextView1
|--ContextView2
I use StageObserverExtension and I do need it, the problem is that when I'm trying to add a View to ContextView2 StageObserver handles addedToStage event and instantiates Mediator set for Context1. Can I avoid it somehow? So I want Context2 views not to be handled by Context1's StageObserver.
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 28 Apr, 2017 12:11 PM
Hi Oleg,
If you take a look at the StageObserverExtension, you can see that there is a single instance of the StageObserver being used throughout the life cycle of an application:
"The Stage Observer Extension adds a single instance. Which listens for everything that is Event.ADDED_TO_STAGE on all root containers in the Container Registry, and then processes the view for you."
StageObserverExtension
https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...
https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...
StageObserver:
https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...
Now, take a look at the ModularityExtension:
https://github.com/robotlegs/robotlegs-framework/tree/master/src/ro...
The first parameter, inherit: Should this context inherit dependencies from a parent context?
Usually, when you want to add a view, say SimpleView to ContextView1 and also another instance of SimpleView to ContextView2, and they should have different mediators, you need to create 2 mappings:
One in you ContextView1 - config:
mediatorMap.map(SimpleView).toMediator(SimpleMediator);
And another in your ContextView2 -config :
mediatorMap.map(SimpleView).toMediator(SimpleMediator);
You set "inherit" to false when you install the ModularityExtension in your child context:
.install(new ModularityExtension(false, false))
And now, each context will handle SimpleView through the correspondingly mapped mediator.
You said:" I use StageObserverExtension and I do need it ".
Does that mean that you can't use a mapping like in my example above?
I hope that helps. Let me know if it doesn't, and provide more details about how you are using the StageObserver.
Ondina
2 Posted by oleg3000 on 29 Apr, 2017 11:08 AM
Hi Ondina, thank you so much for helping me!
Yes I use mapping like in your example and the problem is that StageObserver listens to ContextView1 ADDED_TO_STAGE events in capture phase
https://github.com/robotlegs/robotlegs-framework/blob/master/src/robotlegs/bender/extensions/viewManager/impl/StageObserver.as#L83
, so all ADDED_TO_STAGE events of ContextView2 children will also be handled as ContextView2 is parent of ContextView1. So then SimpleView added to ContextView2 will be handled by Context1 StageObserver.
Looks like the only work-around here is to listen to ContextView2 ADDED_TO_STAGE event in capture phase with higher priority and call stopPropagation() in case ContextView2.contains(event.target) .
I tried Modularity with false,false but It haven't helped. As I understand this extension is only responsible for sharing injector between contexts.
Support Staff 3 Posted by Ondina D.F. on 29 Apr, 2017 05:20 PM
You're welcome, Oleg!
There is only one StageObserver! So, yes, SimpleView will be handled by the same StageObserver, in Context1 and in Context2. But you shouldn't be concerned about the internal working of the framework as long as you are configuring your contexts correctly.
Do I understand you correctly that you are using the StageObserver directly in your code to manage your views? If so, why do you need to do that?
...and mappings, and/or create child-injectors and mappings
"The ModularityExtension allows a context to inherit dependencies from a parent context, and/or expose its dependencies to child contexts."
dependencies==mappings
That works for sure. Without seeing your code I can't say why it doesn't work for you. Would it be possible to show your configs and mappings for the 2 contexts or to attach a simple example illustrating your use case?
Could it be that you are using the same MVCBundle for both contexts?
You can see an example of using the ModularityExtension with different settings:
http://knowledge.robotlegs.org/discussions/robotlegs-2/6915-best-pr...
At the end of the answer there is an attachment that you can download. (ondina-robotlegs-bender-shared-configs ) It is an air application.
And at the end of this message you'll find an example based on the one above, but having just one child context.
You can add SimpleView to the RootContextView
You can add a ChildContextView to the RootContextView
You can add SimpleView to ChildContextView
SimpleMediator is mapped to SimpleView, first inside of RootRobotlegsContext -> MediatorsConfig
and then inside of ChildRobotlegsContext -> ChildContextMediatorsConfig
ChildRobotlegsContext uses a custom MVCSBundle: MVCSBundleTwo where ModularityExtension(false, false)
Look at the traces inside of SimpleMediator and see how each SimpleView is communicating only with the mapped mediator.
Just in case you need to know more about modularity and inter-modular communication:
https://github.com/Ondina/robotlegs-bender-modular-air
https://github.com/Ondina/robotlegs-bender-as3-modular-example
Let me know how it goes.
4 Posted by oleg3000 on 02 May, 2017 06:28 AM
I use StageObserverExtension
Different MVCSBundles, but same mediator-view mapping
Sure, I've changed your example a little https://www.sendspace.com/file/7x1gvv
Support Staff 5 Posted by Ondina D.F. on 02 May, 2017 03:00 PM
Yeah, but the only purpose of StageObserverExtension is to instantiate StageObserver once.
I still don't understand how you use the extension, because the modified example that you've attached is just adding a simple child-context to the root-context.
Also, I don't understand why you need to map SomeView in the root-context and in the child-context. If you don't want the root-context to react to SomeView being added to the stage, you don't create a mapping for it in the root-context.
If you could explain your use case, as in what you want to achieve by having 2 mappings, I might be able to help you. Otherwise I'll just keep guessing different scenarios ;)
In the example I've attached to my previous answer (ondina_simple_child_context) there is a SimpleView added to the root-context and another SimpleView added to the child-context. Each instance has its own mediator.
6 Posted by oleg3000 on 02 May, 2017 03:41 PM
Will try to explain
The project1 contains from A,B,C Views. I want to have a (lets call it widget) widget1 which is actually a copy of project1, but it contains C View only. What do I want is to be able to add that widget1 into the project1 (as a child in view tree), thats why I have same CMediator-CView mappings(I assume contexts are isolated so I define the mapping for both contexts).
In the example I sent I added
mediatorMap.map(SomeView).toMediator(SomeMediator);
mapping to the shell's MediatorConfig, so both child and parent context has got that mapping. When you try to add SomeView to child context - you'll see in logs that SomeMediator is initialized 2 times, so I want to completely isolate child context from the parent one.
In other words, roughly, I'd like to add a copy of Application inside itself, that's why I want to be able to isolate these contexts.
Support Staff 7 Posted by Ondina D.F. on 02 May, 2017 04:52 PM
In the modified example that you added you did not add SomeView to child context.
SomeView IS the view used to build the child context!!!
Each context has a VIEW: the root context (ShellMainView) and the child context (SomeView)
Did you take a look at the example I attached to this discussion? The zip file at the end of my second answer to you?? It's called ondina_simple_child_context .zip
There you can see exactly what you're describing. SimpleView is something like your CView, it can be added to the root-context and to the child-context, as well.
In my example, RootContextView is adding a ChildContextView and a SimpleView. ChildContextView is also adding a SimpleView. The 2 SimpleViews are "isolated" from each other. The SimpleView has a mapping for the root and another for the child context.
Take a look at the example and let me know why is not a good solution for you.
8 Posted by oleg3000 on 11 May, 2017 11:18 AM
Hi Ondina,
I've checked your example - it actually doesn't create second context, as group1_creationCompleteHandler seems to be never called.
I have changed your example a bit to show how to reproduce the issue, what did I do:
Added creationComplete listener to trigger group1_creationCompleteHandler
Added missing interface implementation " implements IConfig" to ChildContextMediatorsConfig and added this config into ChildRobotlegsContext
Added .initialize() call to both contexts
After that you'll se 2 SimpleMediator.initialize() calls in log
9 Posted by oleg3000 on 11 May, 2017 02:25 PM
Changed example in attachment:
Support Staff 10 Posted by Ondina D.F. on 12 May, 2017 11:10 AM
Hi Oleg,
First of all, I can't download your modified example. The zip file seems to be corrupted.
You are right, I made a mistake. I forgot to add the FlexEvent.CREATION_COMPLETE inside of the ChildContextView and the ChildContextMediatorsConfig implements IConfig thing! It probably happened because I first changed my original example (robotlegs-bender-shared-configs) to illustrate the simple_child_context case, but then I decided to create a new project just for that matter. I was in a hurry when I copied and pasted configurations from one project into another and some things got lost on the way...;)
Sorry for that and thanks for the corrections you've made.
That's not needed!!
The contexts will be initialized just fine, because they both have a context view.
See here:
https://github.com/robotlegs/robotlegs-framework#context-initializa...
So, is now everything working as you want it to work? Is your initial problem solved?
Support Staff 11 Posted by Ondina D.F. on 12 May, 2017 02:09 PM
I've got a few minutes to run the corrected example and now I see what you meant. I don't know yet why it's happening. I don't have time right now to look into it. I'll try to find time for this over the week-end or next week.
12 Posted by oleg3000 on 12 May, 2017 02:25 PM
This is happening because there is a parent binding assigned by default for ChildContext
https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...
And then StageObserver triggers all bindings to handle ADDED_TO_STAGE
https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...
I've temporary applied such a crutch, so it works:
containerRegistry.getBinding(contextView.view).parent = null;
Will consider you idea to not to trigger .initialize() seems like this method creates that binding, but project doesn't work properly without it - will get back later when I know if it possible to not to use .initialize()
Thank you again for support!
Support Staff 13 Posted by Ondina D.F. on 13 May, 2017 04:51 PM
Yep. You're right!
If it works for you, go for it, but I think that you somehow could avoid such workarounds.
I've modified my example, again. Hopefully this time without omissions of any kind:)
I hope you'll understand what's going on in spite of the ugly layout.
In this version there are:
RootContextView - root context
ChildContextView with its own context - mediator mapped only in the child context
SharedContextView with its own context - mediator mapped only in the shared context
SimpleView - just a simple component with a mediator mapped only in the root context
So, one hierarchical combination could be:
--- RootContext
------ChildContext
--------- SharedContext
-------------- SimpleView
Or:
--- RootContext
--------- SharedContext
-------------- SimpleView
or:
--- RootContext
------ChildContext
-------------- SimpleView
Since SimpleView does not have its own context, it has been mapped only inside of the root context. Only one new mediator would be created when an instance of SimpleView is added to one of the 3 context-views. So, each instance added to the stage will have its own mediator ( no duplicates).
SharedContext and ChildContext have their own context and mappings. There is no need to map them inside of RootContext as well!
I put SharedContext and SimpleView inside of the commons folder. They could as well be inside of a library of "widgets" or reusable components.
If RootContextView is what you call project1, I still don't understand why you want to add a copy of RootContextView to itself.
Anyway, obviously you'll have to map CMediator-CView only once in the root context.
14 Posted by oleg3000 on 21 Jun, 2017 08:37 AM
Thank you so much for helping Ondina!
Probably you're right and idea of putting context into itself is not such a good idea - but I really need it in my situation)
Unfortunately I stopped to work on it as Flash is dying in our company(
oleg3000 closed this discussion on 21 Jun, 2017 08:37 AM.