Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: need advice for rewrite existing flex app using puremvc  (Read 13180 times)
j4m35bond
Newbie
*
Posts: 6


View Profile Email
« on: March 16, 2009, 07:20:05 »

Hi there,
I have a flex app, which show login panel at beginning, with animation effect. after login, it shows the main app menubar, treeview, working panels, etc.
I put all of these view component within 1 mxml, using some logic to set the visibility for login panels and the nagivation/working  panel.
now I wan to refactor all of these to puremvc framework. any advice on how i can start my work?

I understand that I need to separate some of the viewcomponent into separate mxml and define their own mvc folders with some codes. but what about the animation and state? where to put them together?

any advice will be appreciated. Thanks!

Henry




<mx:Application xmlns:comp="my.customcomponents.*"
   xmlns:mx="http://www.adobe.com/2006/mxml"
   layout="absolute" creationComplete="init()" width="100%" height="100%"
   verticalAlign="middle" horizontalAlign="center">
   <mx:states>
      <mx:State name="showLogin">
         <mx:SetProperty target="{pnlLogin}" name="visible" value="true"/>
         <mx:SetProperty target="{mainApp}" name="visible" value="false"/>
         <mx:SetProperty target="{DBPanel}" name="visible" value="false"/>
         <mx:SetProperty target="{menu}" name="enabled" value="false"/>
      </mx:State>
      <mx:State name="showMainApp">...some states</mx:State>
   </mx:states>
   <mx:transitions>
      <mx:Transition fromState="*" toState="showLogin" >
         <mx:Sequence>
                             /...some transition
   </mx:transitions>
   <mx:Panel id="pnlLogin" width="430" height="224" layout="absolute"
      title="FBI Console - Login Panel" horizontalAlign="center" verticalAlign="middle">
      <mx:Button x="267.5" y="136" label="Login" click="processLogin()"/>
      <mx:TextInput x="163.5" y="45" id="txtUserID" editable="true" enabled="true"
         text="demo"/>
      <mx:TextInput x="163.5" y="90" id="txtPassword" displayAsPassword="true"
         editable="true" enabled="true" text="1234"/>
      <mx:Text x="95.5" y="47" text="User ID : "/>
      <mx:Text x="86.5" y="92" text="Password : "/>
      <mx:Label id="lblLoginStatus" x="86.5" y="138" width="173"  fontFamily="Verdana" fontWeight="bold" color="#0B333C"/>
   </mx:Panel>

   <mx:ApplicationControlBar id="menu" paddingLeft="15" paddingRight="15" dock="true"
      x="0" y="0" width="100%" height="35">
      <mx:MenuBar width="100%" labelField="@label"
         itemClick="itemClickHandler(event);" >
         <mx:XMLList>
            <menuitem label="File">
               <menuitem label="Browser"/>
            </menuitem>
                <menuitem label="CoMa"/>
                <menuitem label="Help" >
                    <menuitem label="About" type="radio" groupName="one"/>
                    <menuitem label="Help" type="radio" groupName="one"/>
                </menuitem>
            </mx:XMLList>
      </mx:MenuBar>
   </mx:ApplicationControlBar>


   <mx:HDividedBox id="mainApp" x="0" y="0" width="100%" height="100%">
      <mx:Panel width="30%" height="100%" layout="absolute">
         <mx:Tree id="tree" width="100%" height="100%" showRoot="false"
            dataProvider="{xmlMap}" itemClick="treeItemClick(event);"
            labelField="@label" iconField="@icon">
         </mx:Tree>
      </mx:Panel>
                        //some others object lies here..

   </mx:HDividedBox>
</mx:Application>





Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: March 17, 2009, 09:41:40 »

Leave your transitions in the MXML, and if your components have states, you can leave those there as well. Your mediators for your view components just feed data to the components and listen for events from them. For instance a mediator can set the currentState property of a component that causes it to change state, which might lead to a visual transition. This is best encapsulated in the component itself rather than orchestrated by other actors.

For application wide state management have a look at the StateMachine Utility. This differs from Flex view states in that it isn't pertaining to a particular component's composition, but rather to the state of the entire system. So in the 'logging in' state you might be displaying a login panel. When the user enters the info and clicks a login button, the component sends an event that the mediator is listening for. The mediator takes the values either from the event if it is a custom event, or simply interrogates its login component for the info (expose a getCredentials method or top-level props like username and password). Then the mediator may retrieve a LoginProxy that makes the login call and later sends an appropriate notification when it gets a result or fault. If it's a good result, this may then lead to a command kicking the state machine into its next state, lets say the 'display products' state. An interested mediator may hear the 'changed' notification sent when the state machine reaches its 'display products' state, causing it to remove the login box and display products.

-=Cliff>
Logged
j4m35bond
Newbie
*
Posts: 6


View Profile Email
« Reply #2 on: March 18, 2009, 01:03:09 »

Thanks for the reply!
That is really impressive response time  :)
I am having an evaluation whetehr I need to choose Cairngorm / pureMVC for my coming Flex application. seems that Puremvc is my choice.
Here I need to ask another question:

Can I create multiple instance of view, tied to single mediator?
<custom:button id="button1" top="0" right="0">
<custom:button id="button2" bottom="0" right="0">

both the buttons will dispatch an event so can 1 mediator listen to both of them? If not, any way I can achieve it without rewriting another mediator class?


Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: March 18, 2009, 04:23:16 »

Yes. The component that they are a part of (or one somewhere up the view hierarchy from them) will have a mediator that will listen for the events. Make the event bubble so you'll be sure it can go up as far as necessary to reach the component the Mediator is listening for.

-=Cliff>
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #4 on: March 18, 2009, 05:53:51 »

I would also add that your mediator could use a custom name retrieved from the component it manages. This allows multiple instances of the same mediator to handle different, but similar, components.
Logged
j4m35bond
Newbie
*
Posts: 6


View Profile Email
« Reply #5 on: March 18, 2009, 08:59:38 »

Hi again,
I have soem problem with this: I have two viewComponent:
      <components:AuthenticationStatus id="wAuthenticationStatus" right="0" top="0"/>
      <components:AuthenticationStatus id="wAuthenticationStatus2" right="0" top="100"/>

In my startup command I include like this:
        override public function execute( note:INotification ):void{          
           facade.registerProxy( new UserProxy() );
           /**
          * Get the View Components for the Mediators from the app,
             * which passed a reference to itself on the notification.
             */
             var app:main = note.getBody() as main;
             facade.registerMediator( new ApplicationMediator(app) );
             facade.registerMediator( new AuthenticationMediator(app.wAuthenticationStatus) );
             facade.registerMediator( new AuthenticationMediator(app.wAuthenticationStatus2) );
        }


The mediator like below:
      public override function handleNotification(notification:INotification):void {
         var body:Object = notification.getBody() as Object;
         switch (notification.getName()) {
            case ApplicationFacade.STARTUP:
               showLoginForm();
               break;
            case ApplicationFacade.AUTHENTICATED_SUCCESS:
               var credentials:UserDescriptor = notification.getBody() as UserDescriptor;
               hideLoginForm();
               setUsername( credentials.username );
               
               break;
            case ApplicationFacade.UNAUTHENTICATED_SUCCESS:
               showLoginForm();
               setUsername("");
               _loginForm.reset();
               
               break;
         }
      }

      private function setUsername(username:String):void {
         this.authenticationStatus.currentUsername = username;
         
      }


      private function get authenticationStatus():AuthenticationStatus {
         return this.viewComponent as AuthenticationStatus;
      }



AuthenticationStatus.mxml has a textbox: currectUsername
   <mx:Text x="10" y="16" width="110" textAlign="right" id="currectUsername" color="#FFFFFF"/>




The problem is, on AUTHENTICATED_SUCCESS, only first viewComponent is updated with userID no matter you click on Login button of first or second component.

Aren't both the object listen to the notification since they are the same mediator class? it should by right update both viewComponent.

in startup command,
changing the sequence:
             facade.registerMediator( new AuthenticationMediator(app.wAuthenticationStatus2) );
             facade.registerMediator( new AuthenticationMediator(app.wAuthenticationStatus) );
won't help but it update only 2nd viewcompoent.

Any idea why is it so?

Thanks
Logged
Joel Hooks
Courseware Beta
Sr. Member
***
Posts: 146


baby steps

 - 46288188  - passport@provinsal.com  - joeltuff
View Profile WWW Email
« Reply #6 on: March 18, 2009, 09:07:04 »

Only one mediator will ultimately be registered with this method. Do a search for dynamic mediators.
Logged

http://joelhooks.com - my ramblings about developing with actionscript and python using pureMVC and django respectively.
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #7 on: March 19, 2009, 04:20:42 »

When you register the same mediator twice, you need to make sure that each instance has a unique name. In the constructor of the mediator, rather than passing its NAME constant to super, pass a unique string. One way to do this is to pass the I'd property of the view component that the mediator in will tend. Another is to add a name parameter to the constructor of the mediator and pass a unique string to it from the command or mediator that instantiates it, such as 'AuthMediator1'

-=Cliff>
Logged
j4m35bond
Newbie
*
Posts: 6


View Profile Email
« Reply #8 on: March 19, 2009, 08:47:12 »

Thanks for the reply!
Since all the component in the main app does assigned with a unique ID, I prefer this way:

super(viewComponent.id, viewComponent);

now it works.

Curious at how the View add the mediator into observer, I looks at your framework source code and here is the one I found  :) -->view.as<--

      public function registerMediator( mediator:IMediator ) : void
      {
         // do not allow re-registration (you must to removeMediator fist)
         if ( mediatorMap[ mediator.getMediatorName() ] != null ) return;
         
         // Register the Mediator for retrieval by name
         mediatorMap[ mediator.getMediatorName() ] = mediator;
                                      .................blah blah blah
                         }


Thanks for the fast reply and great works!

Henry


Logged
Pages: [1]
Print