Flex 4 Login Form Component

It's been a while since I've gotten to blog about Flex 4/Gumbo, and with some exciting news likely coming tomorrow I figured it was time to get back on track. I wanted to think of an example of something that may be frequently used across Flex/AIR projects that will greatly benefit from the Flex 4 architecture and a Login Form seemed like a good place to start. So today we'll review a Login Form component I created in Flex 4. Follow the link to checkout the code from GitHub.

NOTE: This code was compiled using the 7297 revision of the Gumbo SDK trunk.

The LoginForm component extends SkinnableComponent and defines the 3 states ( login , loggingIn , and loggedIn ) & various skin parts. Lets dive into the example skin for the component.

com.smartlogicsolutions.skins.LoginFormSkin

<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">

  <Metadata>
    [HostComponent("com.smartlogicsolutions.components.LoginForm")]
  </Metadata>

  <s:states>
    <s:State name="login" />
    <s:State name="loggingIn" stateGroups="notLogin" />
    <s:State name="loggedIn" stateGroups="notLogin" />
  </s:states>

  <s:VGroup>

    <s:HGroup left="0" right="0" verticalAlign="middle">

      <s:SimpleText id="loginFieldLabel" fontWeight="bold" />

      <s:TextInput id="loginField" enabled.notLogin="false" />

    </s:HGroup>

    <s:HGroup left="0" right="0" verticalAlign="middle">

      <s:SimpleText id="passwordFieldLabel" fontWeight="bold" />

      <s:TextInput id="passwordField" enabled.notLogin="false" />

    </s:HGroup>

    <s:Button id="loginButton" label="Login" enabled.notLogin="false" />

    <s:SimpleText id="loginMessage" excludeFrom="login"
                  text="{hostComponent.loginMessageLabel}" />

  </s:VGroup>

</s:Skin>

The skin provides the essentials for a login form: labels, input boxes, a button, and a label to display what is going on. This skin provides all of the skin parts the LoginForm may display. Of course, the only things a login form must have are the input fields and a button, so these are the only required parts of the component, as seen in this excerpt of the LoginForm component:

(excerpt) com.smartlogicsolutions.components.LoginForm

[SkinPart]
public var loginButton:Button;

[SkinPart]
public var loginField:TextInput;

[SkinPart]
public var passwordField:TextInput;

The labels are all decorated as being optional with the [SkinPart(required="false")] metadata, so any custom skin you provide for the Login Form doesn't have to include the labels if you don't desire.

Once you click the login button, the component puts itself into the loggingIn state and an associated event is dispatched. At this point you would call your service to execute the login, and eventually notify the form the result of the login action. So as for now, in this version of the component, you'll need to explicitly call loginSucceeded() or loginFailed() on the LoginForm instance to signal the result.

Since this is a Flex 4 component, and the view & layout is decoupled from the LoginForm itself, it's dead simple to re-purpose this component across various applications and apply drastically different styles and layouts for all of them. And the only thing that needs to happen is creating another Skin, and specifying that skin when including the LoginForm in your application. Look at the test application file that comes with this component to see how the skin is connected to the form:

TestLoginApplication.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:sls="com.smartlogicsolutions.components.*">

  <Script>
    private function enableButtons(doEnable:Boolean):void {
      btn.enabled = failBtn.enabled = doEnable;
    }
  </Script>

  <s:layout>
    <s:VerticalLayout />
  </s:layout>

  <sls:LoginForm id="loginForm"
                 skinClass="com.smartlogicsolutions.skins.LoginFormSkin"
                 loginLabel="Login:" loggedInMessage="Sweet, logged in!"
                 login="enableButtons(true)" />

  <s:HGroup>

    <s:Button id="btn" label="Set Login Success" enabled="false"
              click="loginForm.loginSucceeded(); enableButtons(false)" />

    <s:Button id="failBtn" label="Set Login Failed" enabled="false"
              click="loginForm.loginFailed(); enableButtons(false)" />

    <s:Button id="updateLoggingInMessage" label="Update Logging In Message"
              click="loginForm.loggingInMessage = 'Trying to login'" />
  </s:HGroup>

</s:Application>

The skinClass property of the LoginForm component will register a skin with the component. In the future, this component would be bundled into a SWC that would apply the skin I've provided by default, but for now you'll need to explicitly apply a skinClass to the component.

I haven't figured out how to properly embed Flash 10 SWFs in wordpress w/o breaking the page for users that don't have it installed, but click through to see the TestLoginApplication in action.

Future features of this component and example will include:

  • validations on the input fields
  • FlexUnit4 tests
  • transitions between the states to demo some Spark effects
  • an extended RegistrationForm class

Enjoy!