tag:robotlegs.tenderapp.com,2009-10-18:/discussions/questions/378-injecting-into-non-rl-spesific-classesRobotlegs: Discussion 2018-10-18T16:35:20Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/41873742010-12-09T16:42:15Z2010-12-09T16:42:15ZInjecting into non-RL spesific classes<div><p>In theory you can use [Inject] in any class, as long as two
conditions<br>
are met:<br>
1. the data type being injected has been mapped with Robotlegs; in
this<br>
case you'd probably map it as a singleton:<br>
// in your context injector.mapSingleton(AssetsModel);</p>
<ol>
<li>Robotlegs needs to know about the class that has the [Inject]
tag in<br>
it -- generally this works best by letting Robotlegs construct
the<br>
instance for you (e.g. mapping it as a singleton, a mediator, a
command,<br>
or just calling injector.</li>
</ol>
<p>However, in your case I'm assuming StyleTextField is some type
of view<br>
class so the "normal" approach in Robotlegs is to <em>not</em> use
[Inject] in<br>
view classes. However, you can achieve pretty much the same thing
by<br>
defining a public property or setter method for your stylesheet
in<br>
StyleTextField. Then use a mediator to set that value.</p>
<p>For example:</p>
<p>// In context: injector.mapSingleton(AssetsModel);<br>
mediatorMap.mapView(StyleTextField, StyleTextFieldMediator);</p>
<p>// in StyleTextField: public function
setStyleSheet(newStylesheet:StyleSheet):void<br>
{</p>
<pre>
<code> this.stylesheet = newStylesheet;</code>
</pre>
<p>}</p>
<p>// in StyleTextFieldMediator [Inject] public var
view:StyleTextField;</p>
<p>// I'm injecting a model in a mediator, which several smart
people frown upon<br>
// I'd love it if they tell us both the alternative =) [Inject]
public var assetsModel:AssetsModel;</p>
<p>override public function onRegister():void<br>
{</p>
<pre>
<code> view.setStyleSheet(assetsModel.stylesheet);</code>
</pre>
<p>}</p>
<p>Of course the key difference between this approach and how
you've done<br>
it before is that (normally) the mediator's onRegister() method
is<br>
called in response to the StyleTextField object's addedToStage
event, so<br>
setStyleSheet won't be called until the StyleTextField is added to
the<br>
stage. That means you'll need to reorder the logic of
StyleTextField a<br>
bit to account for that. For example, in StyleTextField you could
call<br>
init() in response to the addedToStage event rather than in the
constructor.</p>
<p>Paul</p></div>Paul Robertsontag:robotlegs.tenderapp.com,2009-10-18:Comment/41873742010-12-09T18:28:08Z2010-12-09T18:28:08ZInjecting into non-RL spesific classes<div><p>Ok, I'll bite :) Not sure that I'm one of the smart people, but
I do advocate not injecting models into mediators.</p>
<p>So, there are 2 alternatives I use for avoiding injecting models
into mediators:</p>
<p>1) The RelaxedEventMap utility - which basically keeps track of
the most recent firing of each event, and if you register a relaxed
listener then, if the event you're registering for has been fired
before, you'll instantly have the handler run with that most recent
instance of the event.</p>
<p>You can find the util on my github. It's essentially just
time-shifting for event registration. In most other respects it's
identical to the normal eventMap.</p>
<p>2) The sync-signal-response-pair - which is really a pattern
rather than a util, that is implemented like this:</p>
<p>create a strong typed signalton, eg:
AssetsModelDataRequestSignal</p>
<p>This request signal should required a Signal as its dispatch
payload.</p>
<p>This is injected into the mediator, and it's also mapped to a
command, e.g. RespondToAssetsModelDataRequest.</p>
<p>The mediator actually fires the signal, sending (as payload) a
locally created Signal set up to accept the model's data in the
response...</p>
<p>e.g. in your mediator onRegister:</p>
<pre>
<code>var responseSignal:Signal = new Signal(AssetsVO);
responseSignal.add(assetsModelResponseHandler);
requestSignal.dispatch(responseSignal);</code>
</pre>
<p>and (not in onRegister)</p>
<pre>
<code>protected function assetModelResponseHandler(assetsVO:AssetsVO):void
{
// do things using the VO
}</code>
</pre>
<p>Your command just fulfils the request using the response signal,
which is injected because it was the payload of the request signal.
If you needed extra values here - for example if you wanted to
retrieve a particular data set based on user input or the specific
view instance - you would pass that through here as well.</p>
<pre>
<code>[inject]
public var responseSignal:Signal;
[Inject]
public var assetsModel:IAssetsModel
public override function execute():void
{
var assetsVO:AssetsVO = assetsModel.getVO();
reponseSignal.dispatch(assetsVO);
}</code>
</pre>
<p>What does this cost you?<br></p>
<p>2 very small and simple classes for each model you need to
access through the mediator - a Signal, and a Command. Possibly a
VO as well if you weren't already using one.</p>
<p>What does it gain you?</p>
<p>Complete separation of the mediator and the model.</p>
<p>It also allows one specific mediator to get new data while other
instances of the same mediator class carry on unaffected - for
example if you had 3 views on stage that all displayed breaking
news - you could have a button on each that allowed you to grab a
new story immediately. The views can have the same mediators, and
simply fire the request-response signal pattern to refresh their
own data.</p>
<p>So... there is no need to inject a model into a mediator -
though of course robotlegs will let you if that's truly your
heart's desire.</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/41873742010-12-09T18:33:35Z2010-12-09T18:33:35ZInjecting into non-RL spesific classes<div><p>Thanks Stray, I always appreciate learning from you. And
you're<br>
definitely on the list of "smart people" in my book =)</p>
<p>Paul</p></div>Paul Robertson