What follows is a simple experiment in adding login and registration to a Flex Mobile project. There are probably better ways of doing this but my main interest here was to see what was possible. I've done this before with Flex applications. It's not difficult at all. But Flex Mobile has a different way of handling user views. There's a push/pop system that makes it easier to direct the user throughout the application. Specifically I was curious about the tabbed navigator - one of two main views Flex Mobile applications start with - and how it could handle presenting a User/Registration view that could be swapped to the 'real' UI once finished. Again - this was just me playing around to see what was possible. Consider it a proof of concept. Also - I avoided doing "real" login/registration as you will see. Doing network calls in a Flex Mobile application is no more difficult than a traditional Flex application. If readers want to see that, I can definitely make it real. (I'd estimate it would take me longer to FTP the ColdFusion files to my server than it would to actually write the code.)
I began with a new Flex Mobile application that started off with the Tabbed view.
One of the things I really like about Flash Builder is how far it goes to help you get things done quicker. Notice in the UI above I was able to add my two tabs (Login and Registration) before I even finished creating the project. My finished application is going to need more tabs of course, but these are the two initial tabs I'll be starting off with. Once done I can immediately run my application and switch between my Login and Registration views.
Ok - so what next? Remember I said I didn't want to bother with a real login/registration process. I just needed to fake it. I decided to add a simple form with a static login process that once done would 'speak' to my parent application to begin the 'switch to normal' process. Here's the login view:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Login"> <fx:Script>
<![CDATA[
import mx.core.FlexGlobals; protected function handleLogin(event:MouseEvent):void {
if(username.text == "user" && password.text == "password") {
FlexGlobals.topLevelApplication.loadMain();
} else {
statusLabel.text = "Incorrect. (Try user/password)";
}
}
]]>
</fx:Script> <s:layout>
<s:VerticalLayout gap="10" paddingTop="10" paddingLeft="10" paddingRight="10" />
</s:layout> <s:Label text="Username: " />
<s:TextInput id="username" width="100%" /> <s:Label text="Password: " />
<s:TextInput id="password" displayAsPassword="true" width="100%" /> <s:Button label="Login" click="handleLogin(event)" width="100%" /> <s:Label id="statusLabel" color="#FF0000" fontWeight="bold" /> </s:View>
The bottom of this template is just a form. Two labels and a button. I also added a label that will be used for a status message when login fails. If you go to the top and look at the handleLogin function, you can see I've hard coded a valid username and password. The truly important line to focus in on here is this:
FlexGlobals.topLevelApplication.loadMain();
The use of FlexGlobals is something I recently discovered from another Flex Mobile application. By using FlexGlobals.topLevelApplication I get a quick and simple pointer to the top level file of my application. The registration view is even simpler. My form is a little different, but the click handler does even less.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Register"> <fx:Script>
<![CDATA[
import mx.core.FlexGlobals; protected function handleRegister(event:MouseEvent):void {
//Any value for registration is ok with me...
FlexGlobals.topLevelApplication.loadMain();
}
]]>
</fx:Script> <s:layout>
<s:VerticalLayout gap="10" paddingTop="10" paddingLeft="10" paddingRight="10" />
</s:layout> <s:Label text="Username: " />
<s:TextInput id="username" width="100%" /> <s:Label text="Password: " />
<s:TextInput id="password" displayAsPassword="true" width="100%" /> <s:Label text="Confirm Password: " />
<s:TextInput id="password2" displayAsPassword="true" width="100%" /> <s:Button label="Register" click="handleRegister(event)" width="100%" /> <s:Label id="statusLabel" color="#FF0000" fontWeight="bold" />
</s:View>
Ok - hopefully everything so far seems pretty simple. Remember that Flash Builder set up my tabbed navigator and my views for me. I just had to add the forms and the click handlers. If we run the project now we can see both views. Here's a shot of both views.
Now for the fun part. Let's switch to the root file of my application and see what loadMain() is doing. Remember, this function is called after a user has either logged in or registered. Basically, it's where we need to switch the application's UI.
<?xml version="1.0" encoding="utf-8"?>
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations> <fx:Script>
<![CDATA[
import views.*; public function loadMain():void {
trace('called'); var vn1:ViewNavigator = new ViewNavigator();
vn1.firstView = views.HomeView;
vn1.label = "Home";
vn1.percentWidth=100; var vn2:ViewNavigator = new ViewNavigator();
vn2.firstView = views.Part2View;
vn2.label = "Foo";
vn2.percentWidth=100; var vn3:ViewNavigator = new ViewNavigator();
vn3.firstView = views.Part3View;
vn3.label = "Something";
vn3.percentWidth=100; this.tabbedNavigator.removeAll();
//Bug - credit for fix: Dynamic_Internet_Dev and thread: http://forums.adobe.com/message/3702163
this.tabbedNavigator.validateNow();
this.tabbedNavigator.addItem(vn1);
this.tabbedNavigator.addItem(vn2);
this.tabbedNavigator.addItem(vn3); }
]]>
</fx:Script> <s:navigators>
<s:ViewNavigator label="Login" firstView="views.LoginView" width="100%"/>
<s:ViewNavigator label="Register" firstView="views.RegisterView" width="100%"/>
</s:navigators> </s:TabbedViewNavigatorApplication>
So - what's going on here? The TabbedViewNavigator has a few APIs that allow you to change the tabs that are visible. Unfortunately I ran into multiple bugs when working with this API. Luckily there's a work around. Look at loadMain(). I begin by defining thee view navigators objects. These represent my new tabs for the "real" application. HomeView, Part2View, and Part3View were made by me creating new files in Flash Builder.
For now those views don't do anything so I won't bother posting the code here. (But everything will be available in in the download.) Once I've defined my three views, I clear the tab navigator using removeAll. Here is where a bug exists. I initially had just the three addItem's there. When run I'd get an error from within the Flex framework itself. A user (whose name I don't know - but thank you!) from the Flex forums provided the fix you see there - validateNow(). Don't ask me why it works - it just does. The main point though is that we end up with all new tabs within our application. Here's the view after logging in.
That's it. I've included the FXP if you want to play with this yourself. As always - I'm open to alternatives and better ways of doing this.
Archived Comments
the link seems to be broken to the file.
404 - File or directory not found.
The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.
Looks to be an IIS issue. Need to make it treat FXP as binary so it will be downloaded.
Try now please.
All good..thanks!
Boom! this is exactly what I needed. Was previously trying to have a ViewNavigatorApplication that then switches to a TabbedNavigatorApplication - was a bit bulky
P.S. I have a demo on my blog and links to a tutorial on how to get mobile Flex apps to run in the browser... would be really cool for this sort of demo... let me know if you get it up and running:)
Thanks working good .
Is this possible to use the sqlite for storing username and password.
Sure.
Hi Raymond, I found your post very useful but I'm still facing a problem that I can't seem to resolve and maybe you could help me with it (I've been programing on FB for only two months and I'm still on a learning stage).
In your code for username verification, you showed us this:
09 protected function handleLogin(event:MouseEvent):void {
10 if(username.text == "user" && password.text == "password") {
11 FlexGlobals.topLevelApplication.loadMain();
12 } else {
13 statusLabel.text = "Incorrect. (Try user/password)";
Now, I believe that if I type "user" as my username and "password" as the password, the app would allow me to go to the next stage.
Having said that, my main issue comes when I create new users in the registration view. I've created a db using SQLite where I store Users/Passwords but I can't seem to find a validation method so that new users/passwords could function next time I try to login to the app.
Would you mind helping me with that or at least share any link where this problem is solved? I've been surfing the web for over an hour now and I can't seem to find what I'm looking for.
Thanks a lot!
Matt
The main thing would be to change line 10 above to a SQL call that takes in the input and sees if it matches a row in the table. Does that make sense?
Perfect sample!!
You rock!!
After working with Flex Mobile for the past year I find the best practice is to avoid Flex Globals because it severely limits the reuse of code.
The easiest way in my opinion is to completely incapsulate the login as a component and simple create a LoginComponentEvent to pass events from the login into something else.
I usually does this with VGroups if the login will be put in a view or use an actual view if the login is meant to stand alone.
Just my two cents
Hey m very new.. i have used this code bt it throwing exception..
ReferenceError: Error #1069: Property loadMain not found on LoginRegister and there is no default value.
at views::LoginView/handleLogin()[D:\Work\LoginRegister\flex_src\views\LoginView.mxml:11]
at views::LoginView/___LoginView_Button1_click()[D:\Work\LoginRegister\flex_src\views\LoginView.mxml:29]
hey plz tell me how can i remove this..m nt a professional developer but want to develop an app in flex. this is my very first try.. so plz help me ..Thank you.
It looks like either the function is private in your code, can you post the file you are using?
Oh sry sir I loss the code..
Sir will u guide me about developing a mobile application in flex 4.6.?
I can not guide you personally but there is some really good tutorials out there and the adobe evangelicals do a create job of posting updates on their blogs about flex 4.6. I would advise starting there .
how to login out after being load to main application.. pls help tq
when i add icon to vn1, var vn1:ViewNavigator = new ViewNavigator(); like this
vn1.icon = "@Embed('assets/pageimg/my.png')"; it isn't work, can you tell me why. how can i do.
Sorry, I haven't used Flex Mobile in over 2 years.
Is there a way to keep Flex Mobile Application logged in always as of gmail and other mobile applications do, on smartphones. It should ask for login only once and stay logged in even if i don't use application for long, unless i personally logout
You could cache the authentication values locally, but that could be insecure. You could issue a token from the server that is timed, ie, if the remote device passes the token, it auto logs in but the token only works for 7-14 days.
Hey Raymond,
Found this tip on switching tabs really useful, thanks for that. I felt compelled to say thanks, specially when I read that you havent used Flex Mobile in over 2 years. That made me a bit sad ;-) What do you use instead these days? I left for a while too, but came back to Apache Flex 4.14 recently, and am liking the way Flex works again.
By the way, you helped me a fair bit back in the day. Adobe Evangelists were omnipresent in Google, and you and Devgirl always had the answers! Happy days...
Glad to have been helpful. :)
I use Cordova pretty much exclusively. :)