You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@flex.apache.org by CodeGirl <Mi...@yahoo.com> on 2016/08/27 16:26:26 UTC

EventListener null reference error

I have an options panel.

I have a panel which I display an image with the options from the options
panel.

The Options panel has a   Tab Navigator for different categories of Options.

In the parent of both panels, I have my event listeners for all my options.

The problem is that my event listeners for the Navigator Tabs which are not
selected keep giving me a null reference error.  Since the tab is not
selected yet, the MXML Component has not yet been created hence the null
reference error.  

How do I get around this?



--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
Here, I added a powerpoint showing you what my barn app looks like.  Go to my
consultant job and click on the Custom Barn Presentation

https://www.linkedin.com/in/michelle-streeter-62839638






--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13452.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
This was the first app I wrote which used listeners this way, I never thought
of it like that.  But now that most apps are going to mobiles, I guess its
the kind of thinking needed.  Thanks for the help.  Or YTH



--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13457.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by Alex Harui <ah...@adobe.com>.

On 8/29/16, 5:54 AM, "CodeGirl" <Mi...@yahoo.com> wrote:

>The difference was that I was
>going to push up the colorchange event on the click for the tab rather
>then
>the Navigator and then check to see if its the roof tab.  Is there a
>reason
>why you chose the navigator instead of the tab itself?
>

Hmm.  Not sure what you mean.  A Tab is just a button on top of the
TabNavigator.  There is already logic to determine which NavigatorContent
was selected.  Also, I don't like "pushing" an event up.  IMO, at each
level it should be promoted to an event with more meaning so a
"colorChange" becomes a "roofColorChange" using logic encapsulated in the
component that knows which colorChange should becomes a roofColorChange.

Otherwise, you end up with logic higher up that looks like:
if (event.type == "colorChange")
{
  if (event.target == OptionsView)
    // this is a roofColorChange
}

There is no need to do that second test when things are properly
encapsulated, plus the higher logic doesn't need to have a hard reference
to OptionsView.  Then if you decide to swap out OptionsView for
SuperOptionsView, you don't have to change this logic.

HTH,
-Alex


Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
I was thinking about that last night while I was trying to sleep.  Not sure
if I think while I sleep of if I am in and out of sleep and think about
stuff.  But I wondered if that was what you meant.  I was going to test it
today to see if it would work.  My thoughts was slightly different but I C
mine was similar to what you are suggesting.  The difference was that I was
going to push up the colorchange event on the click for the tab rather then
the Navigator and then check to see if its the roof tab.  Is there a reason
why you chose the navigator instead of the tab itself?




--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13470.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by Alex Harui <ah...@adobe.com>.
That still doesn't look quite right to me.  I might not be reading the
snippets you posted correctly.  But let's say you have a main.mxml:

---- main.mxml ----
<s:Application>
  <s:TabNavigator id="tn" change="tabNavChangeHandler()/>
    <ImageView id="imageView" />
    <OptionsView id="optionsView" />
  </s:TabNavigator>
</s:Application>
---- main.mxml ----


The tabNavChangeHandler should have code that looks like:

if (tn.selectedIndex == 1)
  optionsView.addEventListener("roofColorChanged", ...);

In OptionsView, there should be code that looks like:

---- OptionsView.mxml -----
<s:Panel>
  <s:Form>
		
    <s:FormItem label="Colors:" height="200">
      <mx:ColorPicker id="roofColorPKR" width="200" height="50"
        change="roofColorPKR_changeHandler(event)" />
    </s:FormItem>
  </s:Form>
</s:Panel>


And there should be a script block in OptionsPanel.mxml that looks like:
  <fx:Script>
    private function roofColorPKR_changeHandler(e:Event):void
    {
      dispatchEvent(new Event("roofColorChanged"));
    }
  </fx:Script>

What you don't want to see is optionsView.roofOptions.addEventListener in
the main.mxml.  The children should send a semantic event off the
containing component.  You shouldn't have to access the children of the
optionsView to add a listener.

HTH,
-Alex



On 8/28/16, 6:25 PM, "CodeGirl" <Mi...@yahoo.com> wrote:

>I finally found an answer.  Now I wonder if this was what you were saying
>all
>along and I was too focused on adding the event listener rather than
>thinking of scope.  The down side is that I ended up adding four listeners
>to add one that I needed.  So here is how I did it.
>
>in the tab or NavigatorContent, I added a click event and then in the
>click
>event, I fired a Metadata Event.
>Then in the parent, I created the Metadata event from the definition of
>the
>Child Panel.  When that was fired, then I added the color change event
>which
>worked.
>
>Child code
>
>	<fx:Metadata>
>		[Event(name="roofOptionsClicked", type="flash.events.Event")]
>	</fx:Metadata>
>	
>			protected function roofNavigator_clickHandler(event:MouseEvent):void
>			{
>				var eventObject:Event = new Event("roofOptionsClicked");
>				dispatchEvent(eventObject);
>			}
>			
>		<s:NavigatorContent label="Roof" id="roofNavigator"
>click="roofNavigator_clickHandler(event)">
>			<options:RoofOptions id="roofOptions" width="100%" height="100%"
>							  roofcolors="{colors}"
>							  />
>		</s:NavigatorContent>
>		
>
>
>Parent Code
>
>	<options:OptionsView id="optionsView"
>						 width="25%" height="100%"
>						 colors="{colors}"
>						 pitchs="{pitchs}"
>						 roofOptionsClicked="optionsView_roofOptionsClickedHandler(event)"
>						 />
>
>			protected function
>optionsView_roofOptionsClickedHandler(event:Event):void
>			{
>				optionsView.roofOptions.addEventListener(ChangeRoofColor.CHANGED,
>roofOptions_roofColorChangedHandler);
>			}
>			
>			protected function
>roofOptions_roofColorChangedHandler(event:ChangeRoofColor):void
>			{
>
>
>
>
>--
>View this message in context:
>http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-referenc
>e-error-tp13436p13462.html
>Sent from the Apache Flex Users mailing list archive at Nabble.com.


Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
I finally found an answer.  Now I wonder if this was what you were saying all
along and I was too focused on adding the event listener rather than
thinking of scope.  The down side is that I ended up adding four listeners
to add one that I needed.  So here is how I did it.

in the tab or NavigatorContent, I added a click event and then in the click
event, I fired a Metadata Event.
Then in the parent, I created the Metadata event from the definition of the
Child Panel.  When that was fired, then I added the color change event which
worked.

Child code

	<fx:Metadata>
		[Event(name="roofOptionsClicked", type="flash.events.Event")]
	</fx:Metadata>
	
			protected function roofNavigator_clickHandler(event:MouseEvent):void
			{
				var eventObject:Event = new Event("roofOptionsClicked");
				dispatchEvent(eventObject);
			}
			
		<s:NavigatorContent label="Roof" id="roofNavigator"
click="roofNavigator_clickHandler(event)">
			<options:RoofOptions id="roofOptions" width="100%" height="100%"
							  roofcolors="{colors}"
							  />
		</s:NavigatorContent>
		


Parent Code

	<options:OptionsView id="optionsView"
						 width="25%" height="100%"
						 colors="{colors}"
						 pitchs="{pitchs}"
						 roofOptionsClicked="optionsView_roofOptionsClickedHandler(event)"
						 />

			protected function
optionsView_roofOptionsClickedHandler(event:Event):void
			{
				optionsView.roofOptions.addEventListener(ChangeRoofColor.CHANGED,
roofOptions_roofColorChangedHandler);
			}
			
			protected function
roofOptions_roofColorChangedHandler(event:ChangeRoofColor):void
			{




--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13462.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
After some reading, there was a suggestion to use the Event.Change on the tab
but when I tried it, it never fired.  I even tried the TabIndexChanged Event
but it also didnt fire.  I tried to look at the AS and Flex Class info in
hopes of finding out how it was designed but I couldnt find anything about
it.  I googled on what events actually are fired when a tab is selected but
I kept getting hits for something else completely.  I did find someone who
wanted to list this issue as a bug but it never did explain what was how the
programmers intended this issue to be handled.  



--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13461.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
Okay, so I went to the tab Navigator and I put an id on the tab which my
options are on.  Where I want my event listeners is the parent to where the
tab Navigator is located.  So this is great.  Except when I tried to create
an event listener for the tab if it was clicked, I didnt see an okClicked
event.  So I checked for a Clicked event but there isnt one there either.  I
looked for the loginOKClicked and not there.  And neither was the cancel
one.  Any ideas on what to listen on so I can create my listeners when its
instantiated?



--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13459.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by Alex Harui <ah...@adobe.com>.

On 8/28/16, 8:52 AM, "CodeGirl" <Mi...@yahoo.com> wrote:

>You just wonderfully described what I suspected was causing my problem
>and I
>appreciate that it was designed that way.  Except when it came to my event
>listener.  I need to know in a grand parent when an option is changed at
>the
>grand child level.

IMO, while that is technically true, the principle of encapsulation says
that as events propagate back up from child to parent to grandparent, they
should have increasingly more "semantic" information.  IOW, if an MXML
component has two buttons in it, and each of those buttons dispatch a
"click" event, the code for the MXML component (often put in a controller)
should cause the MXML component to dispatch a "okClicked" and
"cancelClicked" event.  The parent of the MXML component then just listens
to the MXML component, for one of those events and adds more semantic
information to any events it dispatches ("loginOKClicked").  IMO, it is
fine to skip levels/generations, but essentially your code shouldn't have
to dig deep.  The code that adds the semantic information should be
instantiated at the same time as the UI widgets it is listening to.  An
event or your code logic should know when it is switching to the Login
panel and attach listeners then.  That is also Pay-as-you-go: no need
delay startup to attach listeners if the user never goes to that panel.

HTH,
-Alex


Re: EventListener null reference error

Posted by CodeGirl <Mi...@yahoo.com>.
You just wonderfully described what I suspected was causing my problem and I
appreciate that it was designed that way.  Except when it came to my event
listener.  I need to know in a grand parent when an option is changed at the
grand child level.  Sure the event wont be triggered until I am in the great
grandchild.  And thats fine.  But the problem is creating the eventlistener
at the great grandparents level when the great grandchild has not yet been
instantiated.  I am not trying to pass data down.  Though I am doing that
and thanks to your description, I may need to rethink that.  But my problem
is not about passing data down but rather setting up an eventlistener up. 
Which yes, it will pass data up too.  I am using an event class to do this. 
In this case, the selected url to the texture I need to use as a skin to my
3D image.  But since my first attempt to describe what is giving me an
error, I will attempt some code.

I have the main app which displays a tab Navigator for the actual app, the
settings, and company.  Here, I am loading all the lookup tables which I do
push down to the children because I have struggled with data not displaying
properly because data has not yet loaded.  Getting the lookup data here has
solved this problem.
The first tab is a Group which is the main app.  Inside this MXML file are
two MXML components which are panels.  Also, this is where I have my event
listeners
One panel is the imagePanel which displays the 3D image with the options
selected in the Options Panel
The second panel is the Options Panel.  In that panel, I have the Navigator
Tabs which associated in each tab is the Barn Options which are the length
width, height, the pitch and barn texture.  
In the Roof Options tab, it lists the roof color, the over hang, and if you
want a facad for the over hang.
The third tab is the Misc Options such as do you want a porch or do you want
vents in the roof and such.

So the grand parent is the where I listen for changes in options and then
passes those changes to the image panel.  So, here is some of my code.  The
first is from the Grand Parent creation complete function.
Notice I have the roof color event listener commented out so my app runs
without error.  Notice that the barn event listeners are fine since that tab
is instantiated automatically.  But I need the roof color changed event
listener.  Well and I will need event listeners for all the other options in
all the options tabs.

			protected function group1_creationCompleteHandler(event:FlexEvent):void
			{
				defaultColorURL = colors.lookupColorByID(defaultcolorID).url;
				defaultRoofColorURL = colors.lookupColorByID(defaultroofcolorID).url;
				imagePanel.barn = new Barn(defaultWidth, defaultLength, defaultHeight,
defaultPitch);
				imagePanel.barn.barnAngle = imagePanel.sidesDDL.selectedItem.angle;
				loaders = new Dictionary();
				images = new Dictionary();
				var urlLoader:URLLoader = new URLLoader();
				urlLoader.addEventListener(Event.COMPLETE,
group1_urlLoaderCompleteHandler);
				urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
				urlLoader.load(new URLRequest(defaultRoofColorURL));
				loaders[urlLoader] = "Roof";
				urlLoader = new URLLoader();
				urlLoader.addEventListener(Event.COMPLETE,
group1_urlLoaderCompleteHandler);
				urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
				urlLoader.load(new URLRequest(defaultColorURL));
				loaders[urlLoader] = "Sides";

				barnSide = defaultsideID;
//				optionsView.roofOptions.addEventListener(ChangeRoofColor.CHANGED,
roofOptions_roofColorChangedHandler);

			
optionsView.barnOptions.barnDimensionsFRM.addEventListener(ChangeWidth.CHANGED,
barnDimensionsFRM_widthSPRChangeHandler);
			
optionsView.barnOptions.barnDimensionsFRM.addEventListener(ChangeLength.CHANGED,
barnDimensionsFRM_lengthSPRChangeHandler);
			
optionsView.barnOptions.barnDimensionsFRM.addEventListener(ChangeHeight.CHANGED,
barnDimensionsFRM_heightSPRChangeHandler);
			
optionsView.barnOptions.barnDimensionsFRM.addEventListener(ChangePitch.CHANGED,
barnDimensionsFRM_pitchGroupChangeHandler);
				optionsView.barnOptions.addEventListener(ChangeColor.CHANGED,
barnOptions_colorChangedHandler);
			}
			
Just in case there might be some reason why you may need to know how I am
firing my events, here is some of the code of one of my grandchildren.


<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx" 
		 xmlns:options="views.options.*"
		 width="400" height="300"
		 >
	
	<fx:Metadata>
		[Event(name="roofColorChanged", type="events.ChangeRoofColor")]
	</fx:Metadata>
	
	<fx:Script>
		
	</fx:Script>
	<s:Form>
		
		<s:FormItem label="Colors:" height="200">
			<mx:ColorPicker id="roofColorPKR" width="200" height="50"
							swatchPanelStyleName="rcpStyle"
							editable="false"
							dataProvider="{roofcolors.dataList}"
							labelField="name"
							colorField="color"
							selectedIndex="{lookupRoofColorsNdx()}"
							change="roofColorPKR_changeHandler(event)" 
							/>
		</s:FormItem>

And here is the event class

package events
{
	import flash.events.Event;
	
	public class ChangeRoofColor extends Event
	{
		public static const CHANGED:String = "roofColorChanged";
		public var url:String;
		
		public function ChangeRoofColor(type:String, url:String)
		{
			super(type);
			this.url = url;
		}
	}
}



--
View this message in context: http://apache-flex-users.2333346.n4.nabble.com/EventListener-null-reference-error-tp13436p13450.html
Sent from the Apache Flex Users mailing list archive at Nabble.com.

Re: EventListener null reference error

Posted by Alex Harui <ah...@adobe.com>.

On 8/27/16, 9:26 AM, "CodeGirl" <Mi...@yahoo.com> wrote:

>I have an options panel.
>
>I have a panel which I display an image with the options from the options
>panel.
>
>The Options panel has a   Tab Navigator for different categories of
>Options.
>
>In the parent of both panels, I have my event listeners for all my
>options.
>
>The problem is that my event listeners for the Navigator Tabs which are
>not
>selected keep giving me a null reference error.  Since the tab is not
>selected yet, the MXML Component has not yet been created hence the null
>reference error.  
>
>How do I get around this?
>

Again, I'm not sure I fully grasped the problem from this description, but
the words "Tab Navigator" and "null" in the same email sounds like you
have a "push-down" vs "pull-down" scenario.  For performance reasons,
things like Tab Navigator try not to instantiate all of their children at
startup.  Thus, starting from the Application, children of the Application
get created, then their children, and so forth until you hit a deferred
instantiation container.  Then those children are only created
"just-in-time".  Otherwise, in really complex scenarios where
TabNavigators have children that contain TabNavigators, lots of component
would get created but potentially never seen and that delays startup time
significantly.

However, the temptation is to write our code to "push down" data to the
children.  Unfortunately, that doesn't work if the children are not yet
created.  So the answer is to have the children "pull down" their data.
You can use data binding, or creationComplete handlers on the children.
This decentralizes your code: the big script block has to get broken into
little bits of code scattered throughout the MXML components, but IMO,
that is actually better encapsulation, and allows deferred instantiation
to maximize performance.

HTH,
-Alex