5 Replies Latest reply on Sep 3, 2009 6:50 AM by karnatis

    Passing parameters between mxml files(used in viewstack).

    karnatis

      Hi All,

       

         In login page, I'm calling RemoteObject method for validating user credentials. In login success, I'd like to keep user name in a variable and call menu page where it is having menu for the application. In menu.xml file, I'm putting home tab is a default selection.

       

          Depending upon login username it should fetch data for displaying DataGrid in home page. Please find my code

       

         //Login Page Begin(login.mxml)

       

        <mx:Script >
              <![CDATA[

         private function login_resultHandler(event:ResultEvent):void
                  {
                      userdetails = event.result as ArrayCollection
                     
                      Alert.show("userdetails 0:",userdetails.getItemAt(0).toString());
                      Alert.show("userdetails 1:",userdetails.getItemAt(1).toString());
                     
                      if(userdetails!=null && userdetails.length>=1)
                      {
                         
                          login_ViewStack.selectedIndex=1;
                      }
                      else
                      {
                          loginmessage.visible=true;
                      }
                  }

      ]]>
          </mx:Script>

       

         <mx:ViewStack x="0" y="0" id="login_ViewStack" width="100%" height="100%" creationPolicy="all" borderStyle="solid">
         
              <mx:Canvas label="loginpage" width="100%" height="100%">
                  <mx:Form x="213" y="137" height="153" width="348">
                      <mx:FormItem width="262" required="false" height="25" label="Username: " fontSize="14" fontWeight="bold">
                          <mx:TextInput id="username_text"/>
                      </mx:FormItem>
                      <mx:FormItem label="Password: " fontSize="14" fontWeight="bold" width="262">
                          <mx:TextInput id="password_text" displayAsPassword="true" enter="ro_login.checkLogin(username_text.text,password_text.text);"/>
                      </mx:FormItem>
                      <mx:FormItem width="265">
                      </mx:FormItem>
                      <mx:FormItem width="251" label="" horizontalAlign="center">
                          <mx:Button label="login" click="ro_login.checkLogin(username_text.text,password_text.text);"/>
                      </mx:FormItem>
                  </mx:Form>
                  <mx:FormHeading x="213" y="109" label="Login Page" width="124" fontWeight="bold" fontSize="16"/>
                  <mx:Text x="213" y="83" text="Invalid Username and password" id="loginmessage" color="#F43D13" fontSize="16" fontWeight="bold" visible="false"/>
              </mx:Canvas>
              <local:menu id="menu_setup" label="" xmlns:local="*"/>
              </mx:ViewStack>

       

         //Login Page End

       

         In checkLogin method, it is validating username/password. and I'm selecting view stack '1' for displaying menu.

       

        //Menu Page Begin(menu.mxml)

        <mx:Script >
               <![CDATA[

      public function init(): void{        
                  myViewStack.visible=true;
                  selectedmenu="HOME";
           }

      ]]>
           </mx:Script>

       

        <mx:Panel  width="100%" height="100%" layout="absolute">
              <mx:ToggleButtonBar id="mainmenu" width="60%" height="39" itemClick="fillsubmenu(event);" dataProvider="myViewStack" buttonMode="true" autoLayout="true" styleName="mystyle" x="118"/>
              <mx:ViewStack id="myViewStack" borderStyle="solid" width="100%" height="465" creationPolicy="all" visible="true"  y="67" x="10">
             
                  <local:home id="page1" label="HOME" xmlns:local="*"/>
                  <local:newcontact id="page2" label="NEW CONTACT" xmlns:local="*"/>
                  <local:search id="page3" label="SEARCH" xmlns:local="*"/>
                  <local:help id="page4" label="HELP" xmlns:local="*"/>
                 
         
              </mx:ViewStack>

       

          </mx:Panel>
         
      </mx:Canvas>

        //Menu Page End

       

        //HOME Page Begin(menu.mxml)

       

        <mx:RemoteObject id="ro_records" destination="inquiryService" result="getInquries_resultHandler(event)"
                           endpoint="http://localhost:7001/flexbb/spring/messagebroker/amf">
              <mx:method name="getInquires" result="getInquries_resultHandler(event)"/>
          </mx:RemoteObject>
         
          <mx:DataGrid id="dg" width="100%" height="100%">
                  <mx:columns>
                      <mx:DataGridColumn dataField="inquiry_id" headerText="Report Id"/>
                      <mx:DataGridColumn dataField="inquiry_type" headerText="Report Type"/>
                      <mx:DataGridColumn dataField="full_name" headerText=" Consumer Name"/>
                  </mx:columns>
            </mx:DataGrid>

       

        //HOME Page End

       

         I'm having following questions:

      1.    How to keep username in session scope. Need to be accessed in all pages.
      2.    How to pass username from login page to home page.
      3.    In HOME page, if I mention 'creationComplete="ro_records.getinquires()"' it will be invoked when I call login.mxml file, so how to invoke getinquires() method passing username when login is successful.

       

       

         Thanks in advance.

       

      Regards,

      Sharath.

       

       

       

        • 1. Re: Passing parameters between mxml files(used in viewstack).
          karnatis Level 1

          Can someone please advice me how to solve this problem.

           

          Thanks,

          Sharath.

          • 2. Re: Passing parameters between mxml files(used in viewstack).
            Gregory Lafrance Level 6

            If this post answered your question or helped, please mark it as such.

             

            To keep username in session scope, so it can be accessed in all pages, and to pass the user name from login to home page, you use custom events, as in my example application. The Flex project archive is attached, but here is the code:

             

            -------------- assets\css\appHeader.css -----------------

            /* CSS file */
            .welcomeLabel{
              fontSize: 20;
              color: #FFFFFF;
              left: 50;
              verticalCenter: 0;
            }

            .titleLabel{
              horizontalCenter: 0;
              verticalCenter: 0;
              fontSize: 24;
            }

            .loginButton{
              right: 30;
              verticalCenter: 0; 

             

            ---------------- com\westernstates\classes\controller\WesternStatesController.as -------------------

            package com.westernstates.classes.controller
            {
              import com.westernstates.classes.events.*;
              import com.westernstates.classes.model.*;
             
              import flash.display.DisplayObject;
              import flash.events.Event;
             
              import mx.core.UIComponent;
              import mx.events.FlexEvent;
              import mx.managers.PopUpManager;

              // This class forms the "controller" of the MVC (Model-View-Controller)
              // architecture used in this application. Rather than have code in the
              // application and in components, the MVC architecture relies on events
              // handled in the controller.

              // Extend UIComponent so this class has a reference to systemManager,
              // so all events that bubble can be handled.
              public class WesternStatesController extends UIComponent{

                // The constructor uses this classes creationComplete event
                // to call the setupEventListeners method to register events
                // with the controller that allow it to "control" much of the
                // application, and also to popup the Login form.
                public function WesternStatesController(){
                  addEventListener( FlexEvent.CREATION_COMPLETE, init);
                }

                // Add event listeners to the system manager so it can handle events
                // of interest bubbling up from anywhere in the application.
                private function init( event:Event ):void{
                  systemManager.addEventListener(LoginEvent.LOGIN, login, true);
                  systemManager.addEventListener(LoginSuccessEvent.LOGIN_SUCCESS, handleLogin, true);
                  systemManager.addEventListener(LoginFailureEvent.LOGIN_FAILURE, handleLogin, true);
                  login(new LoginEvent(LoginEvent.LOGIN));
                }

                private function login(evt:LoginEvent):void{
                  PopUpManager.addPopUp(WesternStatesModel.appLogin, WesternStatesModel.app as DisplayObject, true); 
                }

                private function handleLogin(evt:LoginEvent):void{
                  if(evt.type == LoginSuccessEvent.LOGIN_SUCCESS){
                    WesternStatesModel.userInfo.userName = LoginSuccessEvent(evt).userName;
                    WesternStatesModel.appHeader.currentState = "loginSuccess";
                  }else if(evt.type == LoginFailureEvent.LOGIN_FAILURE){
                    WesternStatesModel.appHeader.currentState = "loginFailure";
                    WesternStatesModel.appLogin.reset();
                  }
                }
              }
            }

             

            ----------------------- com\westernstates\classes\events\LoginEvent.as -----------------

            package com.westernstates.classes.events
            {
              import flash.events.Event;
              /* This custom event is the base class from which other login related 
               * events are derived. This makes it possible to dispatch a login related 
               * event and set the loginEventType property, and then in the event handler, 
               * check this property and execute based on the login event type.
               * 
               * In reality, extending this class doesn't really provide much additional
               * value, but from a conceptual standpoint it might make sense, and as we 
               * develop the application further, we might develop this class further.
              */
              public class LoginEvent extends Event{
                public static const LOGIN:String = "login";   
                
                public function LoginEvent(type:String){
                  super(type, true);
                }
              }
            }
            

             

            ------------------ com\westernstates\classes\events\LoginFailureEvent.as ------------------

            package com.westernstates.classes.events
            {
              import flash.events.Event;
              // This custom event should be dispatched if the user fails to 
              // successfully log into the application.
              
              public class LoginFailureEvent extends LoginEvent{
                public static const LOGIN_FAILURE:String = "loginFailure";   
                public function LoginFailureEvent(){
                  super(LoginFailureEvent.LOGIN_FAILURE);
                }  
              }
            }
            


            ---------------------- com\westernstates\classes\events\LoginSuccessEvent.as -----------------

            package com.westernstates.classes.events
            {
              import flash.events.Event;
              // This custom event should be dispatched if the user 
              // successfully logs into the application.
              public class LoginSuccessEvent extends LoginEvent{    
                public static const LOGIN_SUCCESS:String = "loginSuccess";  
                private var _userName:String;
                 
                public function LoginSuccessEvent(userName:String){
                  // Store the username for the user that successfully logged in.
                  // The application can access the username from the event object.
                  this._userName = userName;
                  super(LoginSuccessEvent.LOGIN_SUCCESS);
                }  
                
                // A getter is necessary for the application to be able to access the private 
                // variable containing the username for the user that successfully logged in.
                // A setter is unnecessary because the username is determined upon login
                // and there is no reason to change it.
                public function get userName():String{
                  return this._userName;
                }
              }
            }
            


            --------------------- com\westernstates\classes\misc\User.as -----------------

            /* This class is used to store information about the user currently logged in.
               The user's password should not be stored here. Currently only the username
               is stored in this class, but later we will add more data.
            */
            package com.westernstates.classes.misc
            {
              [Bindable]
              public class User
              {
                // The public accessor methods (a getter and a setter) allow us to access this private variable.
                private var _userName:String;

                public function User(){
                }
               
                public function get userName():String{
                  return this._userName;
                }
               
                public function set userName(user:String):void{
                  this._userName = user;
                }
              }
            }

             

            ------------------ src\com\westernstates\classes\model\WesternStatesModel.as ---------------

            package com.westernstates.classes.model
            {
              import com.westernstates.classes.misc.*;
             
              import components.*;
             
              import mx.core.Application;

              // This class forms the "model" of the MVC (Model-View-Controller)
              // architecture used in this application. Data that would otherwise
              // be found in the application or component files are centralized here.
             
              public class WesternStatesModel{
                // This variable allows us to enforce having only one model object,
                // and provides an entry point to access the data in the model.
                private static var instance:WesternStatesModel;
               
                // This variable is a convenience obj allowing us to access the
                // main app children when necessary. It would be better to replace
                // this with an event, making even greater use of the MVC architecture.
                public static var app:Object = mx.core.Application.application;

                // This object is used to store information about the user currently logged in.
                [Bindable] public static var userInfo:User = new User();
               
                // References to UI components.
                public static var appHeader:ApplicationHeader = app.appHeader;
                public static var appLogin:Login = new Login();

                // Ensure only one instance of the model exists at any time (singleton).
                public function WesternStatesModel(){
                  if( instance != null ){
                    throw( new Error( "There can only be one instance of WesternStatesModel." ) );
                  }
                }

                // This method is used throughout to access non-static variables of the model.
                public static function getInstance():WesternStatesModel{
                  if( instance == null ){
                    instance = new WesternStatesModel();
                  }
                  return instance;
                }
              }
            }


            -------------------- src\components\ApplicationHeader.mxml ----------------

            <?xml version="1.0" encoding="utf-8"?>
            <mx:ApplicationControlBar xmlns:mx="http://www.adobe.com/2006/mxml"
              width="100%" dock="true">
              <mx:Script>
                <![CDATA[
                  import com.westernstates.classes.events.*;
                  import com.westernstates.classes.model.WesternStatesModel;
                 
                  private function logInOut(evt:MouseEvent):void{
                    if(evt.currentTarget.label == "Login"){
                      this.dispatchEvent(new LoginEvent(LoginEvent.LOGIN));
                    }else{
                      this.currentState = "";
                    }
                  }
                ]]>
              </mx:Script>
              <!--
                This component is the docked control bar at the top of the application,
                where we display a welcome message upon successful login, or a login
                error message for login failure. We also have the main application
                title label, and utility buttons such as Logout/Login.
              -->
              <!--
                The external css file supports our architecture of separating the
                definition of the UI from style rendering.
              -->
              <mx:Style source="../assets/css/appHeader.css"/>
              <!--
                States allow us to control changes in the labels and buttons.
                State changes are managed by the controller class.
              -->
              <mx:states>
                <mx:State name="loginSuccess">
                  <!--
                    The binding braces { } are necessary to resolve the entire welcome
                    string using hard coded pieces and the username in the model.
                  -->
                  <mx:SetProperty target="{welcomeLbl}" name="text"
                    value="{'Welcome ' + WesternStatesModel.userInfo.userName + ' !!!'}"/>
                  <mx:SetProperty target="{welcomeLbl}" name="visible" value="true"/>
                  <mx:SetProperty target="{loginBtn}" name="label" value="Logout"/>
                </mx:State>
                <mx:State name="loginFailure">
                  <mx:SetProperty target="{welcomeLbl}" name="text" value="LOGIN FAILED !!!"/>
                  <mx:SetProperty target="{welcomeLbl}" name="visible" value="true"/>
                </mx:State>
              </mx:states>
              <!--
                Usually we would try to use auto-layout containers, such as VBox, HBox, etc.
                but the application header is a simple component and we want to anchor labels
                and buttons to the left and right sides of the component, or center them,
                and a Canvas and constraint based layout makes this easier. The constraint
                based layout settings are in the css file.
              -->
              <mx:Canvas width="100%" height="100%">
                <mx:Label id="welcomeLbl" text="Welcome !!!" visible="false" styleName="welcomeLabel"/>
                <mx:Label id="titleLbl" styleName="titleLabel" text="Western Gallery of Photography"/>
                <mx:Button id="loginBtn" label="Login" click="logInOut(event);" styleName="loginButton"/>
              </mx:Canvas>
            </mx:ApplicationControlBar>


            ------------------- src\components\Login.mxml -------------------

            <?xml version="1.0" ?>
            <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
              title="Login" horizontalScrollPolicy="off"
              verticalScrollPolicy="off" creationComplete="init();"
              defaultButton="{loginBtn}">
              <mx:Script>
                <![CDATA[
                  import mx.controls.Alert;
                  import com.westernstates.classes.events.*;
                  import mx.collections.ArrayCollection;
                  import mx.managers.PopUpManager;
                 
                  // This test username and password would not be here in a real application.
                  private var testUser:String = "user1";
                  private var testPwd:String = "testme";
                 
                  private function init():void{
                    this.reset();
                    PopUpManager.centerPopUp(this);
                  }

                  public function reset():void{
                    userTxt.text = "";
                    passwordTxt.text = "";
                  }
                 
                  private function login(evt:Event):void{
                    if(userTxt.text == testUser && passwordTxt.text == testPwd){
                      this.dispatchEvent(new LoginSuccessEvent(userTxt.text));
                      this.reset();
                      PopUpManager.removePopUp(this);
                    }else{
                      this.dispatchEvent(new LoginFailureEvent());
                      mx.controls.Alert.show("Login Failed!!!");
                    }
                  }
                ]]>
              </mx:Script>
              <!--
                Currently this login form is very basic. Later we will add validation,
                states, effects, etc.
              -->
                <mx:Form id="loginForm">
                  <mx:FormItem label="Username:">
                    <mx:TextInput id="userTxt"/>
                  </mx:FormItem>
                  <mx:FormItem label="Password:">
                    <mx:TextInput id="passwordTxt"
                      displayAsPassword="true"/>
                  </mx:FormItem>
                </mx:Form>
                <mx:ControlBar horizontalAlign="center">
                  <mx:Button label="Login" id="loginBtn" click="login(event);"/>
                </mx:ControlBar>
            </mx:Panel>


            ------------------ MainApp.mxml -------------

            <?xml version="1.0" encoding="utf-8"?>
            <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
              xmlns:controller="com.westernstates.classes.controller.*"
              xmlns:comp="components.*" viewSourceURL="srcview/index.html">
              <!--
                Because we have broken this application into components, the main application
                file currently does not have much in it. It is possible to argue for simply
                defining the application header here in the main application file, but you
                might use it in other applications or components, so it is implemented as
                a separate component.
              -->
              <!-- The WesternStatesController class. It registers event listeners
                with the systemManager for events that will bubble up the display hierarchy.
                The controller is a non-visual class, although it does extend UIComponent
                so it is on the display list, but it has no visual elements. -->
              <controller:WesternStatesController/> 
              <comp:ApplicationHeader id="appHeader"/>
            </mx:Application>

            • 3. Re: Passing parameters between mxml files(used in viewstack).
              karnatis Level 1

              Thanks Greg.

               

              I have one more question, say after successfully login into your WesternGallary I'd like to show DataGrid for the user who logged into the application.

               

              If I run this program alone its work fine but how to invoke this program from controller and how to initiate applicationComplete event for calling RemoteObject method with logged in username.

               

              I'm having below code(Home.mxml)

               

              <?xml version="1.0" encoding="utf-8"?>
              <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="ro.getStates("user1")">"
                  <mx:Script> 
                      import mx.rpc.events.ResultEvent;
                      import mx.rpc.events.FaultEvent;
                      import mx.controls.Alert; 
                      import mx.utils.ArrayUtil;
                      import mx.collections.ArrayCollection;
                      import mx.utils.StringUtil;
                     
                      public function faultHandler(event:FaultEvent):void
                      {
                          Alert.show(event.fault.faultString, "Error");
                      }
                     
                     
                      private function result(e:ResultEvent):void
                      {
                          dg.dataProvider = e.result as ArrayCollection;           
                      }      

               

                  </mx:Script>
                 
                   <mx:RemoteObject id="ro" result="result(event)" destination="HelloWorld" fault="faultHandler(event)"/>   
                  
                   <mx:DataGrid id="dg" width="100%">
                      <mx:columns>
                           <mx:DataGridColumn dataField="code" headerText="Code"/>
                          <mx:DataGridColumn dataField="name" headerText="Name"/>                     
                      </mx:columns>
                  </mx:DataGrid>
                 
              </mx:Panel>

              • 4. Re: Passing parameters between mxml files(used in viewstack).
                Gregory Lafrance Level 6

                If this post answered your question or helped, please mark it as such.

                 

                I think to do this you can:

                 

                1) add the following to WesternStatesModel.as:

                 

                // References to UI components.
                public static var appHeader:ApplicationHeader = app.appHeader;
                public static var appLogin:Login = new Login();
                public static var appHome:Home = app.myHomeID;            this is the new line to add, the others are for reference

                 

                2) add the following to WesternStatesController.as:

                 

                private function handleLogin(evt:LoginEvent):void{
                  if(evt.type == LoginSuccessEvent.LOGIN_SUCCESS){
                    WesternStatesModel.userInfo.userName = LoginSuccessEvent(evt).userName;
                    WesternStatesModel.appHeader.currentState = "loginSuccess";
                    WesternStatesModel.appHome.ro.getStates(WesternStatesModel.userInfo.userName);           new line to add
                  }else if(evt.type == LoginFailureEvent.LOGIN_FAILURE){
                    WesternStatesModel.appHeader.currentState = "loginFailure";
                    WesternStatesModel.appLogin.reset();
                  }

                }

                where myHomeID is the ID of your Home.mxml instance in the main app file. If it is elsewhere adjust accordingly.

                • 5. Re: Passing parameters between mxml files(used in viewstack).
                  karnatis Level 1

                  Hi Greg,

                   

                      Modified code as you mentioned in earlier post, please find code changes

                   

                     ------------------ MainApp.mxml -------------

                  <?xml version="1.0" encoding="utf-8"?>
                  <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                    xmlns:controller="com.westernstates.classes.controller.*"
                    xmlns:comp="components.*" viewSourceURL="srcview/index.html">
                    <!--
                      Because we have broken this application into components, the main application
                      file currently does not have much in it. It is possible to argue for simply
                      defining the application header here in the main application file, but you
                      might use it in other applications or components, so it is implemented as
                      a separate component.
                    -->
                    <!-- The WesternStatesController class. It registers event listeners
                      with the systemManager for events that will bubble up the display hierarchy.
                      The controller is a non-visual class, although it does extend UIComponent
                      so it is on the display list, but it has no visual elements. -->
                    <controller:WesternStatesController/> 
                    <comp:ApplicationHeader id="appHeader"/>

                    <comp:Home id="myHomeID"/> new line is added
                  </mx:Application>

                   

                    ------------------ Home.mxml ----------------------

                    <?xml version="1.0" encoding="utf-8"?>
                  <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml">
                      <mx:Script> 
                          import mx.rpc.events.ResultEvent;
                          import mx.rpc.events.FaultEvent;
                          import mx.controls.Alert; 
                          import mx.utils.ArrayUtil;
                          import mx.collections.ArrayCollection;
                          import mx.utils.StringUtil;
                         
                          public function faultHandler(event:FaultEvent):void
                          {
                              Alert.show(event.fault.faultString, "Error");
                          }      
                         
                          private function result(e:ResultEvent):void
                          {
                              Alert.show("Home tab with dataprovider:");
                              dg.dataProvider = e.result as ArrayCollection;           
                          }      

                   

                      </mx:Script>
                     
                       <mx:RemoteObject id="ro" result="result(event)" destination="HelloWorld" fault="faultHandler(event)"/>   
                      
                           <mx:DataGrid id="dg" width="100%">
                              <mx:columns>
                                   <mx:DataGridColumn dataField="code" headerText="Code"/>
                                  <mx:DataGridColumn dataField="name" headerText="Name"/>                     
                              </mx:columns>
                          </mx:DataGrid>

                   

                  </mx:Panel>

                   

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

                    Having following issues:

                   

                    1. When accessing it is displaying login page, it is even showing empty DataGrid because we added this component in MainApp.mxml file.

                    2. Even after adding code in controller, it is not calling RemoteObject method.

                   

                    Can you please check these issues and let me know how to resolve this. Sorry to trouble you.

                   

                  Thanks,

                  Sharath.