Link to home
Start Free TrialLog in
Avatar of msukow
msukowFlag for United States of America

asked on

Flex 3.0 simple navigation question

I had the following code originally which worked:
  <mx:Button id="loginButtonID" click="currentState='state1'"
        x="175" y="5" styleName="loginButton" buttonMode="true" cornerRadius="0" />

I now have changed the button to be a component. The click state doesn't work any more because the path is not valid anymore (I think). I tried the following, but it was no good as well:
  <mx:Button id="loginButtonID" click="currentState='/state1'"
        x="175" y="5" styleName="loginButton" buttonMode="true" cornerRadius="0" />

The application mxml is in the same folder as the component folder, which holds the login.mxml component.

What should the click code be?
Avatar of mplord
mplord
Flag of United Kingdom of Great Britain and Northern Ireland image

Where is 'state1' defined? As you've made the button a (presumably MXML) component by itself, you probably want to move the state definition inside the component as well.
I assume state1 is part of the main application ,not the login component.

<mx:Button id="loginButtonID" click="parent.currentState='state1'"
        x="175" y="5" styleName="loginButton" buttonMode="true" cornerRadius="0" />

or

<mx:Button id="loginButtonID" click="Application.application.currentState='state1'"
        x="175" y="5" styleName="loginButton" buttonMode="true" cornerRadius="0" />


The proper way to do this would be to use events:

in your button component code:
<mx:Button id="loginButtonID" click="dispatchEvent( new Event('loginClicked'))"
        x="175" y="5" styleName="loginButton" buttonMode="true" cornerRadius="0" />

and in init function of the module that has the state 1 defined, assuming the login component instance was name 'button1':

button1.addEventListener("loginClicked", doClick);

private function doClick( e:Event):void
{
    currentState = 'state1';
}
Avatar of msukow

ASKER

I updated the code below in the main app, as well as the login component. I know I am close, but I can't quite wrap my head around the process. I now get the following error on line 22 of the main app (loginButtonID.addEventListener("loginClicked", loginClick);)

1120: Access of undefined property loginButtonID.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                xmlns:login="components.*"
                layout="absolute" height="612" width="792"
                backgroundColor="#FFFFFF" backgroundAlpha="0" currentState="initialState">
	
	<mx:Script>
	  <![CDATA[
	    public function captureLoginEvent (event:Event):void
	    {
	      trace("logged in");
	      //click="currentState='productGroupingState'"
	    }
	    
	    private function loginClick( e:Event):void
      {
        currentState = 'state1';
      }
      //
      private function initMSS():void
      {
        loginButtonID.addEventListener("loginClicked", loginClick);
      }
	    
	  ]]>
	  
	  
	</mx:Script><mx:states>
		<mx:State name="initialState">
			<mx:AddChild position="lastChild">
        <login:initialScreen x="0" y="245" width="792"/>
      </mx:AddChild>
      <mx:AddChild position="lastChild">
	      <login:LoginComp x="541" y="10" />
	      
	    </mx:AddChild>
      <mx:AddChild position="lastChild">
        <mx:Image x="150" y="155" source="images/mdiCreativeLogo.swf"/>
      </mx:AddChild>
      <mx:RemoveChild target="{mdiCreativeLogoMainID}"/>
      <mx:RemoveChild target="{monthNavID}"/>
      <mx:RemoveChild target="{cartButtonID}"/>
      
		</mx:State>
		<mx:State name="productGroupingState"/>
      
	</mx:states>
	
	<mx:Style source="supportFiles/Button.css" />
  
  <mx:Style>
      @font-face {
    	src:url("components/supportFiles/fonts.swf");
    	fontFamily: "Helvetica";
  		}
  		@font-face {
    	src:url("components/supportFiles/fonts.swf");
    	fontFamily: "Helvetica";
    	fontStyle: bold;
  		}
  			
	</mx:Style>
	
	<mx:Image id="mdiCreativeLogoMainID" source="images/mdiCreativeLogo.swf"
		        x="28" y="71" height="42.559" width="318.338"/>
 
  <login:monthNavComp  id="monthNavID" y="144" width="792"/>
 
  <mx:Button x="641" y="67.7" styleName="cartButton" id="cartButtonID" width="65.8" height="55.3" click="currentState='cart'" buttonMode="true"/>
</mx:Application>
 
 
---------------------------------------------------------------
 
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" borderThickness="0" borderColor="0x000000">
  <mx:Style source="supportFiles/Button.css" />
  
  <mx:Style>
      @font-face {
    	src:url("supportFiles/fonts.swf");
    	fontFamily: "Helvetica";
  		}
  		@font-face {
    	src:url("supportFiles/fonts.swf");
    	fontFamily: "Helvetica";
    	fontStyle: bold;
  		}
  			
	</mx:Style>
	
    <mx:Script>
                <![CDATA[
                        import mx.controls.Alert;
                        
                        private function checkLogin():void {
                          if(usernameText.text == "user" && passwordText.text == "pass"){
                                Alert.show("Success!");
                          }else{
                                Alert.show("Fail!");
                          }
                        }
                ]]>
        </mx:Script>
        
        <mx:Form id="loginForm" x="0" y="0" verticalGap="3" paddingTop="0" paddingBottom="0" paddingLeft="0" paddingRight="0">  
                <mx:FormItem id="usernameFormItem" label="Username:">
                        <mx:TextInput id="usernameText"/>
                </mx:FormItem>
                <mx:FormItem id="passwordFormItem" label="Password:">
                        <mx:TextInput id="passwordText"/>
                </mx:FormItem>
                <mx:Button id="loginButtonID" click="dispatchEvent( new Event('loginClicked'))"
	      styleName="loginButton" buttonMode="true" cornerRadius="0"/>
                <!--<mx:Button id="loginButtonID" label="Login" click="checkLogin()" styleName="loginButton" buttonMode="true" cornerRadius="0"/>-->
        </mx:Form>
 
</mx:Canvas>

Open in new window

Seems hobbit72 guessed correctly what you were trying to do with states.

OK assuming your loginButtonID control is within your monthNavComp control:

monthNavComp.loginButtonID.addEventListener("loginClicked", loginClick);

OR

monthNavComp.addEventListener("loginClicked", loginClick);
but the click action in your subcontrol needs to be: click="dispatchEvent( new Event('loginClicked', true))" to allow event bubbling from loginButtonID up to monthNavComp.

Avatar of msukow

ASKER

It is actually located in the LoginComp component. I updated the script on the main app to be:

      private function initProgram():void
      {
        LoginComp.loginButtonID.addEventListener("loginClicked", loginClick);
      }

But I don't know how to trigger "initProgram" and I get the following error now:
1119: Access of possibly undefined property loginButtonID through a reference with static type Class.      mdiCreative/src      mdiCreative.mxml      line 22
Avatar of msukow

ASKER

Where should "click="dispatchEvent( new Event('loginClicked', true))" go? On the LoginComp.mxml component?
Difficult to make step by step suggestions when the landscape is changing...

Can you post the code as you now have it?
I'm online for the next 30 mins if you want a quick answer.
Avatar of msukow

ASKER

Main app:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                xmlns:login="components.*"
                layout="absolute" height="612" width="792"
                backgroundColor="#FFFFFF" backgroundAlpha="0" currentState="initialState">
      
      <mx:Script>
        <![CDATA[
          public function captureLoginEvent (event:Event):void
          {
            trace("logged in");
            //click="currentState='productGroupingState'"
          }
          
          private function loginClick( e:Event):void
      {
        currentState = 'state1';
      }
      //
      private function initProgram():void
      {
        LoginComp.loginButtonID.addEventListener("loginClicked", loginClick);
      }
          
        ]]>
        
        
      </mx:Script><mx:states>
            <mx:State name="initialState">
                  <mx:AddChild position="lastChild">
        <login:initialScreen x="0" y="245" width="792"/>
      </mx:AddChild>
      <mx:AddChild position="lastChild">
            <login:LoginComp x="541" y="10" />
            
          </mx:AddChild>
      <mx:AddChild position="lastChild">
        <mx:Image x="150" y="155" source="images/mdiCreativeLogo.swf"/>
      </mx:AddChild>
      <mx:RemoveChild target="{mdiCreativeLogoMainID}"/>
      <mx:RemoveChild target="{monthNavID}"/>
      <mx:RemoveChild target="{cartButtonID}"/>
     
            </mx:State>
            <mx:State name="productGroupingState"/>
     
      </mx:states>
      
      <mx:Style source="supportFiles/Button.css" />
 
  <mx:Style>
      @font-face {
          src:url("components/supportFiles/fonts.swf");
          fontFamily: "Helvetica";
              }
              @font-face {
          src:url("components/supportFiles/fonts.swf");
          fontFamily: "Helvetica";
          fontStyle: bold;
              }
                    
      </mx:Style>
      
      <mx:Image id="mdiCreativeLogoMainID" source="images/mdiCreativeLogo.swf"
                    x="28" y="71" height="42.559" width="318.338"/>

  <login:monthNavComp  id="monthNavID" y="144" width="792"/>

  <mx:Button x="641" y="67.7" styleName="cartButton" id="cartButtonID" width="65.8" height="55.3" click="currentState='cart'" buttonMode="true"/>

</mx:Application>



-------------------------------------------------------

Login component below
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" borderThickness="0" borderColor="0x000000">
  <mx:Style source="supportFiles/Button.css" />
  
  <mx:Style>
      @font-face {
    	src:url("supportFiles/fonts.swf");
    	fontFamily: "Helvetica";
  		}
  		@font-face {
    	src:url("supportFiles/fonts.swf");
    	fontFamily: "Helvetica";
    	fontStyle: bold;
  		}
  			
	</mx:Style>
	
    <mx:Script>
                <![CDATA[
                        import mx.controls.Alert;
                        
                        private function checkLogin():void {
                          if(usernameText.text == "user" && passwordText.text == "pass"){
                                Alert.show("Success!");
                          }else{
                                Alert.show("Fail!");
                          }
                        }
                ]]>
        </mx:Script>
        
        <mx:Form id="loginForm" x="0" y="0" verticalGap="3" paddingTop="0" paddingBottom="0" paddingLeft="0" paddingRight="0">  
                <mx:FormItem id="usernameFormItem" label="Username:">
                        <mx:TextInput id="usernameText"/>
                </mx:FormItem>
                <mx:FormItem id="passwordFormItem" label="Password:">
                        <mx:TextInput id="passwordText"/>
                </mx:FormItem>
                
                <mx:Button id="loginButtonID" click="dispatchEvent( new Event('loginClicked', true))"
	      styleName="loginButton" buttonMode="true" cornerRadius="0"/>
                <!--<mx:Button id="loginButtonID" label="Login" click="checkLogin()" styleName="loginButton" buttonMode="true" cornerRadius="0"/>-->
        </mx:Form>
 
</mx:Canvas>

Open in new window

click="dispatchEvent( new Event('loginClicked', true))"

goes on the loginButtonID button.

You had before:

 <mx:Button id="loginButtonID" click="dispatchEvent( new Event('loginClicked'))"
              styleName="loginButton" buttonMode="true" cornerRadius="0"/>

You would make that:

 <mx:Button id="loginButtonID" click="dispatchEvent( new Event('loginClicked', true))"
              styleName="loginButton" buttonMode="true" cornerRadius="0"/>

to make the event 'bubble'.

Then in your containing control (the application root in this case) you could use:

private function initMSS():void
      {
        monthNavID.addEventListener("loginClicked", loginClick); // this will be 'heard' from the monthNavID control because the event bubbled up from loginButtonID control to it's parent, monthNavID.
      }


However you've changed all the code on us now so the names of your controls have changed, but hopefully you can decipher where we're up to from this.

You don't have to use event bubbling.
Right from the example you posted you could have used:

private function initMSS():void
      {
        monthNavID.loginButtonID.addEventListener("loginClicked", loginClick); // this will be 'heard' from the monthNavID control because the event bubbled up from loginButtonID control to it's parent, monthNavID.
      }

so without bubbling, you would have to listen to the control sending the event directly.

To make initMSS (or now initProgram?) fire, put a 'creationComplete' event on your login control, e.g.

<login:monthNavComp  id="monthNavID" y="144" width="792" creationComplete="initProgram();"/>

1.

You main login component seems to be:
<login:monthNavComp  id="monthNavID" y="144" width="792"/>

This is type 'monthNavComp' - it's id is 'monthNavID'.
'loginButtonID' is the id of a button control within your 'monthNavComp' control

2.
Your initProgram function should be:

private function initProgram():void
      {
        monthNavID.addEventListener("loginClicked", loginClick); // because you allowed event bubbling [click="dispatchEvent( new Event('loginClicked', true))]
      }

3.
For simplicity for now, to get initProgram called, do this:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                xmlns:login="components.*"
                layout="absolute" height="612" width="792"
                backgroundColor="#FFFFFF" backgroundAlpha="0" currentState="initialState"
                creationComplete="initProgram();">

Avatar of msukow

ASKER

Hmmm... LoginComp should handle the login only.

And monthNavComp should just be a component that handles 6 buttons, which display the different months. They should not affect each other. It is obvious I have something wrong with my logic. I tried to send the archived flex files, but it didn't let me. Can I email you the files somehow?
ASKER CERTIFIED SOLUTION
Avatar of mplord
mplord
Flag of United Kingdom of Great Britain and Northern Ireland image

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 msukow

ASKER

Thanks for the hard work - I will look into this tomorrow morning.
Update?