tag:robotlegs.tenderapp.com,2009-10-18:/discussions/robotlegs-2/12920-instantiating-and-initiating-views-with-a-modelRobotlegs: Discussion 2015-07-01T06:41:29Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-19T09:42:50Z2015-05-19T09:42:50Zinitiating views with a model<div><p>Hi,</p>
<p>What you're experiencing is called a "race condition".</p>
<blockquote>
<p>I think this is because the model will be configured before the
view mediator is mapped.</p>
</blockquote>
<p>Or before the mediator is created and ready to react to
events.</p>
<p>I can't draw a schematic representation of the workflow you've
described, but, I hope that you'll get the idea:</p>
<p>1 ----model mapping--------------view/mediator mapping</p>
<p>2 ----model instantiation</p>
<p>3 ---model dispatches event---------------> ** mediator can't
'hear' the event**</p>
<p>4 ----view added to stage triggers--------->mediator
creation</p>
<p>5 ----mediator initialization</p>
<p>6 ----mediator adds event listener for model's event</p>
<p>7 --- nothing happens</p>
<p>You have to make sure that the mediator has already added an
event listener for the event <strong>before</strong> the model
dispatches the event.<br>
Without knowing more about your use case, I'd say that you should
let the mediator add an event listener for a model event, let's
call it LIST_UPDATED, within its initialize() method, then dispatch
an event to request data from the model, LIST_DATA_REQUESTED, that
will trigger a command, that has been injected with the model. The
command accesses a method of the model, and the model dispatches
the LIST_UPDATED event when it is done. The mediator is now able to
handle the event. Important: first add a listener, then dispatch
the requesting event!</p>
<p>The above becomes this:</p>
<p>1 ----model mapping--------------view/mediator mapping</p>
<p>2 ----view added to stage triggers--------->mediator
creation</p>
<p>3 ----mediator initialization</p>
<p>4 ----mediator adds event listener for model's event</p>
<p>5 ----mediator dispatches an event to request the list---->a
command accesses the model's API</p>
<p>6 ----model dispatches event---->mediator handles the
event</p>
<p>Or, you can use the RelaxedEventMap extension:</p>
<p><a href="https://github.com/robotlegs/robotlegs-extension-RelaxedEventMap">https://github.com/robotlegs/robotlegs-extension-RelaxedEventMap</a></p>
<p>Doing work in the constructor of the model is not a good idea.
Take a look at this:</p>
<p><a href="https://github.com/robotlegs/robotlegs-framework/wiki/Common-Problems#injected-properties-are-null-in-constructor">
https://github.com/robotlegs/robotlegs-framework/wiki/Common-Proble...</a></p>
<blockquote>
<p>the model is also instantiating the views.</p>
</blockquote>
<p>Do you really need to do that in the Model? That's usually the
responsibility of the View.</p>
<p>Hope this helps.<br>
Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-20T05:16:03Z2015-05-20T14:23:19Zinitiating views with a model<div><p>Hey Ondina,</p>
<p>thanks for your reply and your detailed explenations :)<br>
I understand the process for initializing views with model
data.<br>
Is there a possibility to have an event fired when all views are
added to the stage?<br>
I just want one single initialization command executed and not one
command for every single view when it is added to the stage</p>
<p>regarding the instantiation of the views within the model.<br>
I am doing this because I wanted to give the list view only the
data it needs.<br>
The calculation which list element will be displayed is done in the
model.<br>
How would you do that? How can the model handle the list items
(sprites) without instantiating them?</p></div>iamabletag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-21T10:55:55Z2015-05-21T10:55:55Zinitiating views with a model<div><p>Hey,</p>
<blockquote>
<p>How would you do that? How can the model handle the list items
(sprites) without instantiating them?</p>
</blockquote>
<p>Hehe, now I'm sorry I've touched that subject at all.<br>
There is no 'one size fits all' solution.<br>
I hope that you're aware of the fact that I cannot answer such a
question without knowing a lot more about your application. But
even if I knew more, finding the best solution would be time
consuming (for me).</p>
<p>From the little I know about your project, I'd say that your use
case would benefit from using the Factory pattern. Probably that
was somehow your intention. A ViewFactory class could be used in a
command, or, better, directly in the view that needs the subviews.
For the latter, you'd inject the factory into the mediator and pass
it to the view.</p>
<p>Take a look at Factory pattern, Fluent builders, Builder
pattern, Fluent interface</p>
<p>Now I see that you added a new question to your message:</p>
<blockquote>
<p>Is there a possibility to have an event fired when all views are
added to the stage?</p>
</blockquote>
<p>I'm sorry, but I don't get it. I don't understand the nature of
your list. When I hear "List", I think of a collection of items,
like in a Menu, usually as strings. It seems that you are talking
about components added to a parent view and you use the term list
like in the "display list" ?</p>
<p>If you added the subviews directly in your parent view, you
could of course know when all suvviews were added to the stage. But
you're adding them in your model....<br>
Are the views that you're manipulating in your model modules that
you're loading somewhere else?</p>
<blockquote>
<p>I just want one single initialization command executed and not
one command for every single view when it is added to the stage</p>
</blockquote>
<p>That's of course possible too, but I don't understand the
workflow, so I cannot answer this either.</p>
<blockquote>
<p>the model has boolean values for each view and when they are
true the corresponding view will be added to the list.</p>
</blockquote>
<p>On what condition it becomes true?</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-21T11:26:48Z2015-05-21T11:26:48Zinitiating views with a model<div><p>OK sorry let me explain the applications flow.</p>
<p>There is a service receiving data from somewhere.<br>
Lets say there are messages coming in like redLight = false,
yellowLight = true, blueLight = false, greenLight = true.<br>
Now I want to have a display list with components which
corresponding signal is true.<br>
So I have components called redLightView, yellowLightView, ...<br>
All the components are extending a LightView and passing their
color to the super class.</p>
<p>My idea was to make the mapping of incoming light signals to
views in the model.<br>
The model has all extended LightViews instatiated.<br>
If this value of the signal changes the corresponding view will be
added or removed to/from an array. whenever that array changed an
event will be fired with the array as payload. The mediator of the
listview listens for it and triggers refreshing the display
list.</p>
<p>I thought the view shouldn't have more calculation than it needs
for displaying things. And I thought the array itself is more a
data base than view calculation.<br>
I think it is not the best way to make the calculation of adding
and removing elements in the array within the list view, isn't
it?</p>
<p>I will have a look at Factory pattern.<br>
I hope we will find a good solution.</p>
<p>Thank you</p></div>iamabletag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-21T13:04:01Z2015-05-21T13:04:01Zinitiating views with a model<div><p>Hey Ondina,</p>
<p>I'd just change my architecure:</p>
<p>adding and removing extended LightViews has moved to the display
list view.<br>
No I'm instatiating the Light Views in that display list view.<br>
The mediator of that display list handles the events for changing
singals.</p>
<p>Now I don't understand where the factory pattern could play any
role.<br>
In addition I don't like the mediator is knowing all the Light
views within the list view and triggers them to add/remove to/from
the list. I think this could be a point to use the factory pattern,
right?<br>
The problem is I doesn't really understand how to use it in this
case.</p></div>iamabletag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-21T17:04:45Z2015-05-21T17:04:45Zinitiating views with a model<div><p>Thanks for providing more details:)</p>
<p>It's evening where I live, so I'll answer your questions
tomorrow as soon as I get a chance.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/368624832015-05-22T10:40:36Z2015-05-22T10:40:36Zinitiating views with a model<div><p>Your workflow + Factory:</p>
<p>At some point in time the model, I'll call it LightsModel,
receives data from a service call and stores it in a collection,
where redLight=true, greenLight=false, etc</p>
<p>The LightsHolderView (I can't come up with a better name right
now) is added to the stage.</p>
<p>A LightsFactory has been mapped asSingleton and was injected
into LightsHolderMediator, and passed to the view in its
initialize() method:</p>
<p>view.lightsFactory = lightsFactory; //the injected one</p>
<p>LightsHolderMediator also adds the event listener mentioned in
the previous posts, and dispatches an event to request data from
the LightsModel from within the initialize() method.</p>
<p>LightsModel sends the dictionary with red=true, green=false,
etc.</p>
<p>LightsHolderMediator passes the payload of the event to the
LightsHolderView, say</p>
<p>view.lightsDataChanged(event.payload);</p>
<p>Within lightsDataChanged, the view iterates through the
collection and for each true value it adds a LightView to its
stage. Something like this:</p>
<pre>
<code>public function lightsDataChanged (lights:Dictionary):void
{
for(var lightColor:String in lights)
{
if(lights[lightColor]==true)
{
addChild(_lightFactory.createView(lightColor));
}
}
}</code>
</pre>
<p>Of course you can also remove views. This is just pseudocode for
the sake of an example.</p>
<p>The LightsFactory can hold a lightDictionary, where greenLight,
redLight, yellowLight..etc, are the keys and GreenLightView,
RedLightView are the values, as classes. (
lightDictionary["greenLight"] = GreenLightView; )</p>
<pre>
<code>public function createView(lightColor:String): ILightView
{
return new lightDictionary[lightColor]();
}</code>
</pre>
<p>When you're done with adding/removing subviews, you can of
course dispatch an event for the mediator to hear and do whatever
it needs to be done.</p>
<p>The LightsModel is now concerned only with the data and the
state of that data. What happens if greenLight is true or false is
not Model's concern anymore. A View (or more views and other
classes) could react to that info in different ways, some by
drawing green circles, others by drawing green squares, or by
playing some music and so on. A lot can happen inside an
application because the greenLight==true;)</p>
<p>Of course you can hold a dictionary of colors/view classes (not
instantiated) in the model itself or in a VO, that would be sent to
the mediator/view. In this case you don't need a factory. The view
just iterates through the dictionary, instantiates the subviews and
adds/removes them accordingly. This kind of model is surely not as
'clean' as the one above, but sometimes it might be useful.</p>
<blockquote>
<p>In addition I don't like the mediator is knowing all the Light
views within the list view and triggers them to add/remove to/from
the list. I think this could be a point to use the factory pattern,
right?</p>
</blockquote>
<p>You're right, LightsHolderMediator shouldn't have to know about
the children of LightsHolderView, be it a GreenLightView or a
PinkLightView or a VariegatedView.</p>
<p>The LightsHolderMediator is just passing the data from the model
to the view.</p>
<blockquote>
<p>I thought the view shouldn't have more calculation than it needs
for displaying things. And I thought the array itself is more a
data base than view calculation.</p>
</blockquote>
<p>What do you mean by "calculation"? The decision which view to
add or to remove?<br>
In my example, the decision has been made in the model
(greeen=false, red=true), and the view is just "reading the
directives" in a loop and does its job.</p>
<p>On another note, you might have a good reason to have a
RedLightView, a YellowLightView, etc, but it sounds to me like the
only thing that differentiates them is the color. If so, then you
only need one Class, LightView implementing a ILightView with a set
color method.</p>
<p>Here is an example of a factory:</p>
<p><a href="https://github.com/Stray/robotlegs-examples-OreillyBook/blob/master/mosaictool/src/mosaic/view/grid/TileFactory.as">
https://github.com/Stray/robotlegs-examples-OreillyBook/blob/master...</a></p>
<p>Are things more clear now?</p></div>Ondina D.F.