tag:robotlegs.tenderapp.com,2009-10-18:/discussions/questions/937-separating-of-view-creation-and-filling-it-with-dataRobotlegs: Discussion 2012-08-14T17:47:25Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/165562692012-06-10T00:12:55Z2012-06-10T00:12:55ZSeparating of view creation and filling it with data<div><p>Hello!<br>
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?</p>
<p>Regards!</p></div>Lukentag:robotlegs.tenderapp.com,2009-10-18:Comment/165562692012-06-10T18:57:10Z2012-06-10T18:57:13ZSeparating of view creation and filling it with data<div><p>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. :/</p></div>Lukentag:robotlegs.tenderapp.com,2009-10-18:Comment/165562692012-06-12T00:28:10Z2012-06-12T00:28:59ZSeparating of view creation and filling it with data<div><p>When a View is created, it <em>can</em> 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.</p>
<p>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.</p>
<p>What have you tried, and what specific issues are you having</p></div>Amytag:robotlegs.tenderapp.com,2009-10-18:Comment/165562692012-06-12T07:45:39Z2012-06-12T07:45:40ZSeparating of view creation and filling it with data<div><p>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.</p>
<ol>
<li>I can just put the data in the constructor of the view,</li>
<li>I can send from just created view a request to its model, so it
will send me the data it got from click once more.</li>
</ol>
<p>And I'm wondering what would be the best approach.</p>
<p>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 :) .</p>
<p>Regards.</p></div>Lukentag:robotlegs.tenderapp.com,2009-10-18:Comment/165562692012-06-12T12:34:58Z2012-06-12T12:34:59ZSeparating of view creation and filling it with data<div><p>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.</p>
<p>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.</p>
<p>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.</p></div>Amytag:robotlegs.tenderapp.com,2009-10-18:Comment/165562692012-06-13T14:50:26Z2012-06-13T14:50:26ZSeparating of view creation and filling it with data<div><p>Luken,</p>
<p>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:</p>
<p>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.</p>
<p>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
<code>super(Signal)</code> 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.</p>
<p>Try and experiment a bit and see which you prefer. Just come
back here if you need more help.</p>
<p>Abel</p></div>Abel de Beer