views:

914

answers:

4

Is there a way to temporary swap Flex's main application to another then switch back. Scenario : Main app started, display login box - then go on with main app. Login box is an application as well.

Application.application is a read only property, that attempt failed.

+1  A: 

Is there a reason why you cannot make the login box a component and then perhaps use a ViewStack to control the viewable components?

mmattax
A: 

That's funny, this is exactly what I am attempting to figure out the best way to do at the moment. I had thought of using a ViewStack, but as I already have a lot of other nested ViewStacks being used, I was also looking into the State tag. If anyone knows "the right thing" to do I'll be very interested too!

defmeta
A: 

I've implemented this as a ViewStack on the Application component; seems to work fine. Use the selectedIndex or selectedChild property on the ViewStack to control whether the login or the app UI is displayed.

<mx:Application>
  <mx:ViewStack>
    <mx:Box> <!-- or whatever for login-->
    </mx:Box>
    <mx:Box> <!-- application UI widgets here -->
    </mx:Box>
  </mx:ViewStack>
</mx:Application>
Mitch Haile
+2  A: 

I've had great success with a modular application whereby the main application basically consists of a module loader, that initially loads a logon module.

Once the logon module has done it's stuff (in my case validated inputs, called the logon service and retrieved a token), it dispatches an event (imaginatively called "LogonEvent") that contains details required by the main application. I should point out that the logon module itself is just a wrapper for a logon component that does all the real work (so the logon component can be used in a module or ViewStack etc). Having a LogonEvent makes all the difference.

The wrapper application processes the logon event by unloading the logon module, loading the main module that contains the guts of the application, and then sets the required logon details on the loaded module.

The log off button is in the wrapper application so that it can unload the main module and reload the logon module ready for logging in again.

The benefit of this kind of layout is that the relatively small logon module loads pretty quickly. And while the user is logging on, the main module is already getting pre-loaded, so there is generally no wait for the main module to load after log on. If you have one large monolithic application the initial load time could be off putting.

Some bits of code that may help...

private var mainModuleLogOnEventDispatcher:*;

[Bindable]
private var _logOnDetails:LogOnDetails = new LogOnDetails();

private function onCreationComplete(event:Event):void
{
 // Load log on module.
 loadMainModule("LogOnModule.swf");

 // Pre-load main module while user is logging on.
 var mm:IModuleInfo = ModuleManager.getModule("MainModule.swf");
 mm.load();
}

[Bindable]
private function set logOnDetails(value:LogOnDetails):void
{
 _logOnDetails = value;
}

private function get logOnDetails():LogOnDetails
{
 return _logOnDetails;
}   

private function loadMainModule(moduleName:String):void
{
 // Unload anything already loaded.
 if (mainModule.url.length > 0)
 {
  mainModule.unloadModule();
  mainModule.url = "";
 }
 mainModule.addEventListener(ModuleEvent.READY, handleMainModuleReadyEvent);
 mainModule.url = moduleName;
}

private function handleMainModuleReadyEvent(event:ModuleEvent):void
{
 // Remove listener, we've caught the event now.
 mainModule.removeEventListener(ModuleEvent.READY, handleMainModuleReadyEvent);

 // Add listeners to other events or apply data.
 if (mainModule.url == "LogOnModule.swf")
 {
  mainModuleLogOnEventDispatcher = mainModule.child;
  if (mainModule.child != null) {
   mainModuleLogOnEventDispatcher.addEventListener("logOnEvent", handleLogOnEvent);
  }
 }
 if (mainModule.url == "MainModule.swf")
 {
  var mm:* = mainModule.child;
  if (mainModule.child != null)
  {
   mm.logOnDetails = logOnDetails;
  }
 }           
}

private function handleLogOnEvent(logOnEvent:LogOnEvent):void
{
 mainModuleLogOnEventDispatcher.removeEventListener("logOnEvent", handleLogOnEvent);

 logOnDetails = logOnEvent.logOnDetails;

 // Now get person's details and swap in main module if successful.
  var parameters:Object = new Object();
  parameters.cmd = "viewPerson";
  parameters.token = logOnDetails.logOnToken;
 viewPersonRequest.send(parameters);
}

private function handleViewPersonRequestResult(event:ResultEvent):void
{

 //*** Loads of setting logonDetails and error handling removed!!! ***//
 loadMainModule("MainModule.swf");
 currentState = "LoggedOn";
 return;
}

private function onLogOff(event:MouseEvent):void
{
 // Make sure we don't auto-logon when we log off.
 var logOnPrefs:SharedObject = SharedObject.getLocal("LogOn", "/");
 logOnPrefs.data.loggedOff = true;

 var parameters:Object = new Object();
 parameters.cmd = "logoff";
 parameters.token = logOnDetails.logOnToken;
 logoffRequest.send(parameters);
 loadMainModule("LogOnModule.swf");
 currentState = "";
}

<!-- *** Loads of view state related mxml removed *** -->
<mx:VBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle" id="mainModuleVBox">
 <basic:IJModuleLoader id="mainModule" url="" width="100%" height="100%" horizontalAlign="center" verticalAlign="middle"/>
</mx:VBox>

I should also note that this wrapper application isn't actually an application! This is actually a module itself, which is loaded by either a Flex or AIR application. This way I can have separate Flex and AIR projects that reference a core library project that holds the application module, logon module, main (post logon) module and basically all other components and classes used by the application.

ianmjones