Solved

Flex: Changing property of inactive state

Posted on 2009-04-14
6
2,451 Views
Last Modified: 2013-11-11
I have a decision tree wizard where the first states in the workflow determine what is shown in the last states.  

I ran into a bug where if I change the enabled state of an element in a state which has not yet been viewed - I get the following error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
      at stateChangeExample/check2Handler()[/.../src/stateChangeExample.mxml:25]
      at stateChangeExample/___stateChangeExample_CheckBox2_click()[/.../src/stateChangeExample.mxml:49]

I have included code for an example.  You'll notice that if you select the checkbox on the right before you hit the change state button, you'll get the error.  If you then change the state and then change it back you will no longer get the error.

I have a couple workarounds... namely run through all the states onLoad or buffer all the changes until the state is set to currentState... but I prefer to figure this out.  Maybe there is a way I need to activate the state without showing it?

HELP!!!
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:states>
		<mx:State name="state2">
			<mx:AddChild position="lastChild">
				<mx:TextInput id="input2" x="203" y="41"/>
			</mx:AddChild>
		</mx:State>
	</mx:states>
	<mx:Script>
		<![CDATA[
			public function check1Handler():void
			{
				if(input1.enabled == true)
				{
					input1.enabled = false;
				} 
				else
				{
					input1.enabled = true;	
				} 	
			}
			public function check2Handler():void
			{
				if(input2.enabled == true)
				{
					input2.enabled = false;
				} 
				else
				{
					input2.enabled = true;	
				} 					
			}
			public function changeState():void
			{
				if(currentState == "state2")
				{
					currentState = "";
				} 
				else
				{
					currentState = "state2";	
				} 	
			}
		]]>
	</mx:Script>
	<mx:CheckBox click="check1Handler()" x="10" y="11" label="disable/enable in base state"/>
	<mx:TextInput id="input1" x="10" y="41"/>
	<mx:CheckBox click="check2Handler()" x="203" y="11" label="disable/enable in state2"/>
	
	<mx:Button click="changeState()" x="10" y="71" label="Change State"/>
	
	
	
</mx:Application>

Open in new window

0
Comment
Question by:bittermonk
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
6 Comments
 
LVL 2

Accepted Solution

by:
hockeyragazzo earned 500 total points
ID: 24140868
This has likely got something to do with the fact that input2 hasn't yet been instantiated in the display. I often run into problems like these when I have a custom component with a bunch of textinputs and I want to insert data into those inputs directly (input2.text = "Blah blah") before they've been added to the display. The solution I use in this case is to bind variables to the text inputs and simply set the variables. Absent other solutions that help you better understand the nature of the accessibility of display objects when they're not in the stage, how about this:

Set the enabled property equal to some Boolean variable called Input2EnabledBool which starts at whatever state you like (true or false). This way you can set the value of Input2EnabledBool = false when you want to disable the TextInput and = true when you want to enable it. As far as I know, this will solve your problem.

Be sure to put a [Bindable] tag before your variable:

[Bindable] private var Input2EnabledBool = true;

and then:



<mx:State name="state2">
                        <mx:AddChild position="lastChild">
                                <mx:TextInput id="input2" x="203" y="41" enabled={Input2EnabledBool}/>
                        </mx:AddChild>
                </mx:State>

Open in new window

0
 
LVL 2

Expert Comment

by:hockeyragazzo
ID: 24140967
An alternative, yet more bloated (especially if you have many TextInputs on which you want to perform these operations), option is to put your input2 with visible=false in the main portion of the Application instead of creating it in the new state. Then, instead of adding a TextInput in your new state, simply set the visible property = true. This will ensure that it exists at every point after creationComplete and all you will be changing when you go into a new state is the visibility of input2.

I personally like the variable binding option better because states are an extremely efficient way to add components in a way that doesn't add much to the size of the Application/component you're building.
0
 

Author Comment

by:bittermonk
ID: 24140968
hockeyragazzo: Your answer is better than what I went with...

So to be clear... if I change the currentState and then change it back...

the element in state2 is not on the stage until state2 is set to currentState
and
when I return to the base state the element in state2 remains on the stage although it is no longer visible.

Is there a way to add all the states to the stage onLoad without making them visible?
0
Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

 

Author Comment

by:bittermonk
ID: 24140985
I definitely like the binding option better than removing the states...
0
 
LVL 2

Expert Comment

by:hockeyragazzo
ID: 24141017
According to my understanding, that is correct. You can test this out by entering some text into your TextInput and switching states back and forth. If the text remains in the box after going to the base state and back to state2, then I think that is a correct interpretation.

As far as I know, adding all the states to the stage, i.e. adding all the components in a state to the stage, would defeat the purpose of having states. The only way to accomplish this would be to set a creationComplete function to just run through all the states you want to load and then back to your base state. I suspect that in a larger application, and possibly even in smaller ones like yours, this would start looking pretty clunky to the user. The same effect can be achieved by adding your component in the main part of the Application (as if it were in the base state), but setting the visibility = false, then using states to manipulate the visible property. This does come at a cost as every component in the main portion of the Application adds to the size of the .swf you produce on export, while adding components with states is a low-cost alternative to this.

But considering this is the only scenario I can really think of where states kind of screw with what the programmer expects to occur, binding variables to your state-added components is probably the best solution.

Lemme know what you end up going with and how it works out for you....or if you need any more clarification :-)
0
 

Author Closing Comment

by:bittermonk
ID: 31570000
Thanks for the clarification... I'll go with this :)
0

Featured Post

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This is intended to introduce all collision detection principles in flash, their strengths, weaknesses and workarounds. The main method for Collision Detection in flash is using hitTestObject. But unless you'll be pushing rectangular shapes without …
This article describes a solution to a problem of subloading one movie into another when they have different SWF versions. Sometime back, I was working on an ActionScript project while I came across an interesting fact which I would like to share…
In this tutorial viewers will learn how to create a basic shape tween animation in Flash including shape hints for smooth animation Open a new document in Flash: Draw a shape: Select another frame (how long you want the tween to be): Right click and…
This Micro Tutorial will teach to how to utilize bit rate in Adobe Flash Media Live Encoder.

737 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question