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-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