Link to home
Start Free TrialLog in
Avatar of bittermonk
bittermonkFlag for United States of America

asked on

Flex: Changing property of inactive state

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

ASKER CERTIFIED SOLUTION
Avatar of hockeyragazzo
hockeyragazzo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of hockeyragazzo
hockeyragazzo

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.
Avatar of bittermonk

ASKER

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?
I definitely like the binding option better than removing the states...
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 :-)
Thanks for the clarification... I'll go with this :)