tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/259-null-error-on-sub-view-in-commandRobotlegs: Discussion 2018-10-18T16:35:23Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T18:29:07Z2011-02-15T18:29:07ZNull error on sub-view in Command<div><p>Dude - this is a nice easy one...</p>
<pre>
<code>var squareView:SquareView = new SquareView();</code>
</pre>
<p>Should really be</p>
<pre>
<code>squareView = new SquareView();</code>
</pre>
<p>You're assigning it to a local property instead of the class
member variable.</p>
<p>Oops! (easily done)</p>
<p>That said... injecting views into commands isn't really the
conventional approach. The norm would be to pick up the event in a
mediator for view stuff. Commands are really for model / service
access.</p>
<p>But, for now, your bug is fixable!</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T18:33:47Z2011-02-15T18:33:47ZNull error on sub-view in Command<div><p>Ah! Duh, you're right, stupid mistake. I had been mixing code
and forgot to switch it back, sloppy on my part.</p>
<blockquote>
<blockquote>
<p>injecting views into commands isn't really the conventional
approach.<br>
The norm would be to pick up the event in a mediator for view
stuff.<br>
Commands are really for model / service access.</p>
</blockquote>
</blockquote>
<p>OK - good to know! I had used Commands in Cairngorm previously,
and had done a lot of view stuff in them. Need to rewire my brain
to the Robotlegs way of thinking, thanks again!</p>
<p>Jason Merrill Instructional Technology Architect Bank of America
Global Learning</p>
<p>_______________________</p>
<p>-----Original Message----- From: Stray [mailto:<a href=
"mailto:tender+d0f3e998cffee7458325bddbf82598bac91d163e7@tenderapp.com">tender+d0f3e998cffee7458325bddbf82598bac91d163e7@tenderapp.com</a>]<br>
Sent: Tuesday, February 15, 2011 1:29 PM<br>
To: Merrill, Jason<br>
Subject: Re: Null error on sub-view in Command [Problems]</p></div>jason.merrilltag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T19:10:38Z2011-02-15T19:10:38ZNull error on sub-view in Command<div><p>Cool - no problem - I find those kinds of things the hardest to
debug when it's my own code.</p>
<p>The usual approach would be that the mediator for the parent
view picks up the event and then runs api on the parent view -
which could be a view-controller that contains view-stuff, or might
be a composite that has view-controllers to pass off functionality
to if the same functionality repeats in various places.</p>
<p>The basic idea behind it is that you shouldn't mix your
framework with your view, because then your view needs your
framework in order to run. It's very much possible to achieve most
view stuff in the view layer, and then only use the robotlegs
classes to join your view to the application (and thus other views
as well).</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T19:17:47Z2011-02-15T19:50:03ZNull error on sub-view in Command<div><p>OK cool. So how would you recommend, from the parent mediator
(i.e. CompositeShapeViewMediator), I reference and listen to the
sub-views (i.e. squareView) inside of compositeShapeView for
example? Would I inject an instance of CompositeShapeView inside of
CompositeShapeViewMeditator?</p>
<pre>
<code> //CompositeShapeViewMediator.as
[Inject]
public var compositeShapeView:CompositeShapeView;
//then when the event is heard:
compositeShapeView.squareView.x += 10;</code>
</pre>
<hr>
<p>so, for example,</p>
<pre>
<code> package landingPage.mediators
{
import landingPage.events.BallViewEvent;
import landingPage.view.CompositeShapeView;
import org.robotlegs.mvcs.Mediator;
public class CompositeShapeViewMediator extends Mediator
{
[Inject]
public var compositeShapeView:CompositeShapeView;
public function CompositeShapeViewMediator()
{
super();
compositeShapeView.ballView.addEventListener(BallViewEvent.BALL_VIEW_CLICKED, onBallViewClicked)
}
private function onBallViewClicked(event:BallViewEvent):void
{
compositeShapeView.squareView.x += 10;
}
}
}</code>
</pre>
<hr>
<p>If so, didn't you say yesterday that you wouldn't normally
inject views? I saw a reference in the Robotlegs documentation that
had an injection of a view into a mediator, but is this not
recommended?<br></p>
<p>And the code above, doesn't seem to work - the instance of
compositeShapeView is null, even though in my Context I have:</p>
<pre>
<code> var compositeShapeView:CompositeShapeView = new CompositeShapeView();
injector.mapValue(CompositeShapeView, compositeShapeView);</code>
</pre>
<p>Jason Merrill</p></div>jason.merrilltag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T19:58:28Z2011-02-15T19:58:28ZNull error on sub-view in Command<div><p>Hi Jason - basically the only view injection that I'd normally
do is the injection of the view into its mediator.</p>
<p>I'm not really clear enough on what you're trying to achieve
here -</p>
<p>where does the action initiate? What is it that the user has
clicked? Is it a button somewhere?</p>
<p>Normally actions on sub views would be taken by the parent
view.</p>
<p>So you might expose an API like moveItem(.... ) on the
compositeShapeView.</p>
<p>Can you explain a bit more about your process?</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T20:22:32Z2011-02-15T20:22:32ZNull error on sub-view in Command<div><blockquote>
<p>basically the only view injection that I'd normally do is the
injection of the view into its mediator</p>
</blockquote>
<p>Yes, and that is what I am trying to do here. This is just a
test HelloWorld app, but basically, the user clicks on ballView,
which dispatches BallViewEvent.BALL_VIEW_CLICKED. Both ballView and
squareView are children of CompositeShapeView.</p>
<p>When BallViewEvent.BALL_VIEW_CLICKED is heard, it should move
the squareView 10 pixels.<br></p>
<p>The problem right now, is that the compositeShapeView is, for
some reason I cannot explain, <em>null</em> inside of the instance
of CompositeShapeViewMeditator class where it is injected. My
context looks like this (snippet)</p>
<pre>
<code> mediatorMap.mapView(CompositeShapeView, CompositeShapeViewMediator);
var compositeShapeView:CompositeShapeView = new CompositeShapeView();
injector.mapValue(CompositeShapeView, compositeShapeView);</code>
</pre>
<p>The mediator is as I have shown in the previous post. Any ideas
why compositeShapeView is coming up null?</p></div>jason.merrilltag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T20:47:29Z2011-02-15T20:55:51ZNull error on sub-view in Command<div><p>You don't need the mapValue mapping.</p>
<p>Just do</p>
<pre>
<code>mediatorMap.mapView(CompositeShapeView, CompositeShapeViewMediator);</code>
</pre>
<p>and when your CompositeShapeView hits the stage, the mediator
will be created for it and, assuming you've got something like</p>
<pre>
<code>[Inject]
public var view:CompositeShapeView</code>
</pre>
<p>inside your mediator, it should be injected.</p>
<p>You should be aware that injection happens
<strong>after</strong> the constructor runs (There is a big list of
'common problems' that is linked to on the main page for stuff like
this by the way - really worth a read).</p>
<p>So - while it'll always be null in the constructor, it should be
there when <code>onRegister</code> runs.</p>
<p>The problem you're having is partly that there is no need to
pass events of the nature you're describing through the robotlegs
framework. It doesn't make sense. You would just listen for
<code>ballView</code> being clicked in the
<code>CompositeShapeView</code> and then run a function to move the
square view...</p>
<p>Generally, robotlegs only helps to wire together parts of the
view that are separate - for example if this was a
drawing-application, and the user changed the colour of the current
selected item, you'd send a <code>ColourEvent.COLOUR_CHANGED</code>
event and that might get picked up by the main drawing stage
area.</p>
<p>I think you're going to really struggle to get a good
understanding of robotlegs working with view-related code only.
That's not where it's intended to help you.</p>
<p>Let's assume that you've got a menu with 4 buttons that can
nudge something up, down, left or right, and both the ball and the
square on the stage, and that it's possible for either the ball or
the square to be the 'currently selected item' in the
CompositeShapeView.</p>
<p>We want the current selected item to be nudged in the right
direction when the user clicks one of the nudge buttons.</p>
<p>To achieve this, we might have the following classes:</p>
<pre>
<code>NudgeMenu
NudgeMenuMediator
NudgeEvent
CompositeShapeView
CompositeShapeViewMediator</code>
</pre>
<p>With code snippets like this:</p>
<p>NudgeMenu:</p>
<pre>
<code>protected function listenForNudgeClicks():void
{
btnLeft.addEventListener(MouseEvent.CLICK, createNudgeHandler(-10, 0))
btnRight.addEventListener(MouseEvent.CLICK, createNudgeHandler(10, 0))
btnUp.addEventListener(MouseEvent.CLICK, createNudgeHandler(0, -10))
btnDown.addEventListener(MouseEvent.CLICK, createNudgeHandler(0, 10))
}
protected function createNudgeHandler(xNudge:Number, yNudge:Number):Function
{
var handler:Function = function(e:MouseEvent):void {
var e:NudgeEvent = new NudgeEvent(NudgeEvent.NUDGE_REQUESTED, xNudge, yNudge);
dispatchEvent(e);
}
return handler;
}</code>
</pre>
<p>NudgeMenuMediator:</p>
<pre>
<code>public override function onRegister():void
{
// this just redispatches the event to the whole application
addViewListener(NudgeEvent.NUDGE_REQUESTED, dispatch);
}</code>
</pre>
<p>CompositeShapeViewMediator:</p>
<pre>
<code>public override function onRegister():void
{
addContextListener(NudgeEvent.NUDGE_REQUESTED, passNudgeToView);
}
protected function passNudgeToView(e:NudgeEvent):void
{
compositeShapeView.nudgeCurrentSelectionBy(e.x, e.y);
}</code>
</pre>
<p>CompositeShapeView</p>
<pre>
<code>public function nudgeCurrentSelection(xNudge:Number, yNudge:Number):void
{
_currentSelectedShape.x += xNudge;
_currentSelectedShape.y += yNudge;
}</code>
</pre>
<p>Does that make a bit more sense? Here we're using the robotlegs
framework to decouple the nudge controls from the subject of the
nudges.</p>
<p>HelloWorld is always a bit difficult because in the real world
nobody would use a framework for a HelloWorld size application!</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-15T21:58:41Z2011-02-15T22:05:50ZNull error on sub-view in Command<div><p>Thanks, no I got it - I am only listening to view events like
Click and staying within views. The other events were only to test
out the RL framework and how events pass around.<br></p>
<p>This morning I thought Commands were used on views as well, but
I see now how they generally wouldn't be.<br></p>
<p>Thanks for your detailed response. The key was what you
mentioned about the injection happening after the constructor runs.
I put the necessary code in an</p>
<pre>
<code> override public function onRegister():void
{
}</code>
</pre>
<p>method in the mediator and it's working fine now. Thanks for
your help! Great stuff, I've got a lot to go on now. I already have
some model code working in RL and that was pretty straightforward -
so my questions were really about working with views
correctly.<br></p></div>jason.merrilltag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-16T16:48:55Z2011-02-16T16:48:55ZNull error on sub-view in Command<div><p>Great - glad you're sorted :)</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-16T17:38:52Z2011-02-16T17:38:52ZNull error on sub-view in Command<div><p>Thanks yeah - so let me ask one more question if I may. If you
wanted a view to respond to changes in the model, you would inject
a singleton of the model into the view's mediator, and then listen
to the event on that model, and create a handler to alter the view,
right? That's my MVC way of thinking, but would you instead use a
Command?<br></p>
<p>Jason Merrill Instructional Technology Architect Bank of America
Global Learning</p>
<p>_______________________</p>
<p>-----Original Message----- From: Stray [mailto:<a href=
"mailto:tender+d0f3e998cffee7458325bddbf82598bac91d163e7@tenderapp.com">tender+d0f3e998cffee7458325bddbf82598bac91d163e7@tenderapp.com</a>]<br>
Sent: Wednesday, February 16, 2011 11:49 AM<br>
To: Merrill, Jason<br>
Subject: Re: Null error on sub-view in Command [Problems]</p></div>jason.merrilltag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-16T17:48:11Z2011-02-16T17:48:11ZNull error on sub-view in Command<div><p>Hi Jason - robotlegs provides the shared eventDispatcher - which
is injected into any class that extends Actor and into
Mediators.</p>
<p>So - your model would dispatch the event on the shared
eventDispatcher, and the mediator would just listen for it on the
shared eventDispatcher.</p>
<p>You don't need to inject the model into the mediator.</p>
<p>You should really check out some of the demos that are around -
look in the Examples section of the forum and you'll get a feel for
it.</p>
<p>Thanks,</p>
<p>Stray</p></div>Straytag:robotlegs.tenderapp.com,2009-10-18:Comment/53624182011-02-16T17:54:56Z2011-02-16T17:54:56ZNull error on sub-view in Command<div><p>Thanks - yeah, been through a lot of the demos - I just forget
easily. :) Thanks.</p>
<p>Jason Merrill Instructional Technology Architect Bank of America
Global Learning</p>
<p>_______________________</p>
<p>-----Original Message----- From: Stray [mailto:<a href=
"mailto:tender+d0f3e998cffee7458325bddbf82598bac91d163e7@tenderapp.com">tender+d0f3e998cffee7458325bddbf82598bac91d163e7@tenderapp.com</a>]<br>
Sent: Wednesday, February 16, 2011 12:48 PM<br>
To: Merrill, Jason<br>
Subject: Re: Null error on sub-view in Command [Problems]</p></div>jason.merrill