Login System For A Flex Application With ColdFusion Backend Part 3 - Custom Login Form Component
Introduction To Part 3 - Custom Login Form Component
When I finished part 2 of this project, I had successfully connected my Flex application to the ColdFusion backend. Now I could finally get to work on designing the actual login form of my Flex application. My initial design question was how should I build the login form? I could include all the mxml and action script in the same application that will be used for the newsletter or I could design a custom login form component. I decided to design a custom login form component since I could then reuse the login form in other applications. Also, while I'm designing the custom login form component, other developers could be working on the main newsletter application.
References
- Adobe Flex Documentation, Creating and Extending Flex 2 Components
- Bruce Phillips Blog, For Flex 2.0 Beginners - Use the mx:States and mx:ViewStack Tags To Change The Application's View
If you're not familiar with how to create simple custom components in Flex or how to use the mx:ViewStack tag then consult the above references. You may also want to review parts 1 and 2 of this project (see related entries below).
Initial Design
To keep this initial design simple and to get a working prototype, I recalled my first use case stated in part 1:
A. User visits the application and the login screen loads. User is already a member. User enters user name and password correctly. User information is validated by comparing user information to information stored in a database. User supplied information matches what is found in the database. User is shown the main application.
So in building my custom Login form I needed to have the basic functionality to meet the above use case. You can view a demo of the custom login form in a working Flex application; right click on the application to view all the source files. Enter phil1021 for the username and seven for the password to login.
Custom Flex Component Notes
My custom Flex component, called LoginForm, extends the Form tag. Inside this custom component is all the code to create a simple login form, connect to the backend CFC, and process the results returned by the CFC.
I wanted to make my custom component somewhat independent (loosely coupled) from the actual application. So my custom component would need to have a couple of advanced features: dispatching a custom event and providing access to a variable. These features of custom components are very well explained in reference 1, pages 91-112.
Declaring a custom event is simple. Here's the code:
[Event(name="loginSuccess", type="flash.events.Event")]
</mx:Metadata>
The above code defines a new custom event named loginSucess. When the CFC getMemberByUserNameAndPassword method returns a Member object--thus indicating the provided username and password were correct--I have the custom LoginForm component dispatch this event.
In the main GeekNews mxml file, I specify this event when adding the LoginForm to my application.
So when the custom LoginForm component dispatches the loginSucess event, the GeekNews application calls the handleLoginSucess function. If you examine the source code (see link above), you'll note that in the handleLoginSucess function I change the ViewStack's selected child to the main application view.
Now I also want the main GeekNews application to have a reference to the Member object that is returned by the CFC when the userName and password are found in the table. Since this Member object will be returned to the custom LoginForm component, I need a way to get the Member object when inside my main GeekNews application. Here is the code from the custom LoginForm component that sets up a Member object variable and provides a public get method that will allow outside components to access it.
//object returned by the CFC method private var __member:Member;
// Define a getter method for the private variable. public function get member():Member {
return __member;
}//end get member
To get the above __member object from within the main GeekNews application I just need to use the value of the id attribute of the custom LoginForm component (in my code I used login for the id value). The following code is in the function handleLoginSuccess which is called when the custom LoginForm component dispatches the loginSucess event. Right now the main GeekNews application is just using the Member object's firstName field (see the welcome message after a successful login).
//the LoginForm component aMember = login.member ;
What's Next?
If you view the demo and enter phil1021 and seven you'll see that I've successfully completed a prototype that satisfied my very simple first use case. In the next iteration of the project, I'll add the capability for the LoginForm component to handle an incorrect username and password (right now just an Alert box pops up with the error message returned by the CFC). This will satisfy a branch of our first use case: If the user provides an incorrect username or password, provide the user with an error message and allow the user to try again. I may also had some validation to the LoginForm's textinput tags.
Please feel free to provide feedback, criticism, and even better suggestions/examples of how to do this better.
Why not use setRemoteCredentials in your remoteObject and use cflogin at the server side ?
I had actually used setRemoteCredentials and cflogin in a previous project and I wrote about it in my blog (see:
/blog/index.cfm/2006/...).
However, I ran into a problem with cflogin. If the user did not actually logout, but just closed the browser, and then returned before their session expired on the ColdFusion server, they could not log back in. Therefore they could not advance to the main application. Flex would show the user the login form, the user would try to login again, and cflogin would not work correctly on the ColdFusion side.
I think this problem is discussed in the comments on the that blog entry.
Also, since I don't really need role security for the user, this simpler login system seems more robust.
Bruce
you could call ro.logout() or eventually a ro.someLoutOut function which could call <cflogout for you.
we use it and never run into problems.
Thanks kindly,
Shawn
I think studying my Login Form blog entries would be helpful. If you right click on the application example, you can download all the source code. You'll need to change the structure of the member table to include a role column. Then you will be able to use the member's role value to determine which ActionScript and CFC functions that user can execute.