Separating of view creation and filling it with data
Hello!
It's probably a simple question, yet I wasn't able to find a clear
answer and I'm quite a noob besides >_<. As in the title, I
have a one parent view that contains a few children, that are
dynamically created (so they may or may not to be needed in a
single run of an application, they also may be of various types
based on what loader service will provide). I would like to be able
to create a child view only when it is needed, but I have a problem
how to adopt a typical Robotlegs flow to that. Normally the
mediator fills view with data, but in my case, the view and
mediator doesn't exist yet, when user will click a button. So the
child view, cannot get that loaded data at first click. The parent
view however can catch proper event, use it as a signal for
creating a child view and pass the data instantly to it. It would
be nice but is it a right approach? I feel that would make a code
less clear, as I will be listening for the same events in parent
view and children. Parent will use it to create smaller ones and
then would remove a listener, but what if the child-view needs to
disappear? Or is not useful anymore? The parent would need to add
his listeners once more so it could be able to create a smaller
views once more if they would be needed. I can imagine that it can
be quite a mess. So the question is - what is a best approach for
such a simple goal as creating new views and filling it with
data?
Regards!
Comments are currently closed for this discussion. You can start a new one.
2 Posted by Luken on 10 Jun, 2012 06:57 PM
It would be best if anyone would have any examples of projects with dynamically created views of different types and filling them with data, after certain events. I just cannot imagine it overall. Where to put a factory etc. :/
3 Posted by Amy on 12 Jun, 2012 12:28 AM
When a View is created, it can receive injections as soon as you add it to the stage. You set this up by adding the Class of the View that you will instantiate to the ViewMap. RobotLegs watches for it to be added, and it will provide its dependencies with any other information you've mapped in the Injector.
Mediators are automatically created in the same way. So it doesn't matter if your Views are created dynamically or not. That's the whole point of Robotlegs.
What have you tried, and what specific issues are you having
4 Posted by Luken on 12 Jun, 2012 07:45 AM
I know, but the problem is that in the normal flow the click on UI element, will call a loader, that will change a value on the proper model, but now - the view doesn't exist yet, so it cannot get information about first model update. I can use that event (click) for creating that view, but I need to put somehow the data related to that click into the view as well. I have several options to do that and I'm not sure what is best.
And I'm wondering what would be the best approach.
First seems more natural, but what if I want to "cache" view at some point, so I removed it from display list and later I need to update it after showing it again? I would need to send a request for data anyway. And second doesn't look too clear. I hope that I put it clear, sorry if my considerations are chaotic :) .
Regards.
5 Posted by Amy on 12 Jun, 2012 12:34 PM
The best approach is "neither." Views should NOT be responsible for retrieving their own data. That data should be retrieved somewhere else, preferably in a separate service layer that will then spawn off one or more Commands to update the Model.
If you do it in a more robust, best-practice way as I've suggested, you then have the option to reuse your Views or not--it really doesn't matter, since they will always receive the most up-to-date data.
I know it gets confusing when you have examples like Adobe's "generated service" examples, which nearly always have these things handled in the View. But those examples are more what you'd do if you were dashing off a quick prototype, not something you can build on for full production code.
6 Posted by Abel de Beer on 13 Jun, 2012 02:50 PM
Luken,
I would recommend against passing the data through the constructor. Generally you're more flexible when using the Mediator's onRegister and onRemove methods to populate its view. The easy (and dirty) way would be to inject the Model into the Mediator, but a more loosely coupled way is what Stray once coined as the Request-Provide Pattern:
If you're using Events, the process is rather straightforward: Create a custom event class, i.e. ViewDataProviderEvent, with a REQUEST and PROVIDE string constant. Make sure you also add a (preferably strongly typed) data property. In your Context's startup method, map ViewDataProviderEvent.REQUEST to i.e. ProvideViewDataCommand. Inject your Model into the ProvideViewDataCommand, and in its execute method you dispatch ViewDataProviderEvent.PROVIDE, along with the Model data. Now in your Mediator's onRegister method, add a listener for ViewDataProviderEvent.PROVIDE which populates your view using the data that is passed with the event. Lastly, dispatch a ViewDataProviderEvent.REQUEST event from the onRegister method.
If you're using Signals, you'll be using a (request data) signal that accepts and dispatches a (provide data) signal: Create a custom Signal class, i.e. RequestViewDataSignal, and add
super(Signal)to its constructor. In your Context's startup method, use the signalCommandMap to map the RequestViewDataSignal class to i.e. ProvideViewDataCommand (don't use the previous one :P ). Inject your Model into the ProvideViewDataCommand, and also inject a signal, i.e. provideViewData, with type Signal (should be the same type as the one you added to the RequestViewDataSignal constructor). In the ProvideViewDataCommand's execute method you dispatch the provideViewData signal, passing along the Model's data as its argument. Inject the RequestViewDataSignal in your Mediator. In its onRegister method, create a new Signal, i.e. provideData, with the Model's data type (maybe Array, or a VO) as its argument. Add a listener to this Signal which accepts the data type and populates your view. Lastly, dispatch the RequestViewDataSignal instance from the onRegister method, passing along the provideData signal as its argument.Try and experiment a bit and see which you prefer. Just come back here if you need more help.
Abel
Ondina D.F. closed this discussion on 14 Aug, 2012 05:47 PM.