Customizing the Login Box – Part 3 – Validation with FB4, PHP and MySql

In this tutorial we will continue with the Login Box that we have been building in the last several tutorials. In this tutorial we are going to cover how to validate using a string validator and email validator. There are a number of validators available as well, but once you have the basic concept down, you will be able to implement the others without a hitch.

Lets Get Started

The first thing you need to do is figure out what fields you want to validate. In our case, we have six, as follows:

1. Username <loggedOut>

2. Password <loggedOut>

3. Email <forgotPW>

4. Username <register>

5. Email <register>

6. Password <register>

The second thing that you need to do is figure out if there are going to be any buttons that should be disabled/enabled based on TextInput field validation. In our case, the answer is yes:

1. Login <loggedOut>

2. Get Login Info <forgotPW>

3. Save <register>

Also, we need to note that we want the button in each state to be disabled until ALL textInput fields in the respective state pass validation.

Now that we have outlined our goals, you need to think about the validation rules, or what constitutes each field being considered valid.  For the Username and Password fields, we just want to make sure that they are over six (6) characters long, and for the email address, we want to make sure that the properties of the string match that of a properly formed email address.

Importing the Necessary Classes

import mx.events.ValidationResultEvent;
  import mx.rpc.events.ResultEvent;
  import mx.validators.EmailValidator;
  import mx.validators.StringValidator;

Creating Variables

private var usernameVal:StringValidator = new StringValidator();
  private var passwordVal:StringValidator = new StringValidator();

private var emailVal:EmailValidator = new EmailValidator();

private var emailVal2:EmailValidator = new EmailValidator();
  private var usernameVal2:StringValidator = new StringValidator();
  private var passwordVal2:StringValidator = new StringValidator();

Now that the variables have been created and the classes have been imported, we need to follow a series of steps for each state.

1. Write the Validation Function

2. Set the default state of the respective button to disabled

3. Decide when and how you want to call the function

loggedOut State Validation

In this state you have the username and password TextInput fields to validate. These two fields are only being validated to ensure that they have over 6 characters each. We will start by making the necessary changes to the loggedOut state to prepare it.

Step 1. Changes to State Components

Here, we are going to add the change event on each of the text boxes, add an id and enabled properties to the “Login” button.

Change From:

<s:TextInput x="77" y="13" includeIn="loggedOut" id="username"/>

Change To:

<s:TextInput x="110" y="10" id="username" change="loggedOut_changeHandler(event)" includeIn="loggedOut"/>

Change From:

<s:TextInput x="77" y="43" displayAsPassword="true" includeIn="loggedOut" displayAsPassword="true" id="password"/>

Change To:

<s:TextInput x="110" y="40" id="password" change="loggedOut_changeHandler(event)" displayAsPassword="true" includeIn="loggedOut"/>

Change From:

<s:Button x="8" y="72" label="Login" click="login_user.send();" includeIn="loggedOut"/>

Change To:

<s:Button x="10" y="72" id="loginBtn" label="Login" click="login_user.send();" enabled="false" includeIn="loggedOut"/>

Note: In the above code we have chosen to call loggedOut_changeHandler using the change event for the TextInput field. There are other events we could have chosen such as focusOut. The reason we are using the change event however, is so that as soon as the field has met the validation, the “Login” button will become enabled rather than waiting for the user to leave the TextInput field. It could be argued that this takes more system resources because it is checking validation on every text change, but the difference is really negligible. Nevertheless, use the method you feel most comfortable with.

Step 2. Validation Function

The function loggedOut_changeHandler could have been split up into two separate functions and would normally be written that way if we were not basing the login button enabled property on the validation of multiple TextInput fields.

protected function loggedOut_changeHandler(event:TextOperationEvent):void
  {
  if (username.text)
  {
  var valUsername:ValidationResultEvent;
  usernameVal.source = username;
  usernameVal.property = "text";
  usernameVal.minLength=6;
  }
  if (password.text)
  {
  var valPassword:ValidationResultEvent;
  passwordVal.source = password;
  passwordVal.property = "text";
  passwordVal.minLength=6;
  }
  valUsername = usernameVal.validate();
  valPassword = passwordVal.validate();
  if(valUsername.type == "valid" && valPassword.type == "valid")
  loginBtn.enabled = true;
  else
  loginBtn.enabled = false;
  }

Step 3. Changes to getCookie_resultHandler

Because you have the username and password TextInput boxes set to validate on the change event, when a cookie is set, the “Login” button is disabled and the only way to enable it is to make a change in one of the text boxes. To avoid this little problem, we have set loginBtn.enable = true;. We can do this because now that we are validating, we know that any cookie set will have already undergone validation. The getCookie_resultHandler should now look like:

protected function getCookie_resultHandler(event:ResultEvent):void
  {
  if(event.result.storedCookie == true)
  {
  cookieAction = true;
  username.text = event.result.creds.username;
  password.text = event.result.creds.password;
  loginBtn.enabled = true;
  }
  else
  {
  cookieAction == false;
  }
  }

Step 4. Run and Test the application. Check to make sure that it is working both with and without the cookie set.

Flex 4 - textInput Validation

“forgotPW” State Validation

In this section we will check for validation on the email address of the forgotPW state. Here we are only checking to make sure that the email address is formatted correctly, not wether it is a working email address or not.

Tip: For more information on the validation criteria, you can view EmailValidator.as by holding Command and clicking “EmailValidator” in the import statement.

Step 1. Changes to State Components

Change From:

<s:TextInput x="110" y="39" id="email_to" includeIn="forgotPW"/>

Change To:

<s:TextInput x="110" y="39" id="email_to" change="email_to_changeHandler(event)" includeIn="forgotPW"/>

Change From:

<s:Button x="8" y="72" label="Get Login Info" click="get_password.send();" includeIn="forgotPW"/>

Change To:

<s:Button x="8" y="72" id="emailBtn" label="Get Login Info" click="get_password.send();" enabled="false" includeIn="forgotPW"/>

Step 2. Validation Function

protected function email_to_changeHandler(event:TextOperationEvent):void
  {
  if (email_to.text)
  {
  var valEmail:ValidationResultEvent;
  emailVal.source = email_to;
  emailVal.property = "text";
  }

 valEmail = emailVal.validate();
  if(valEmail.type == "valid")
  emailBtn.enabled = true;
  else
  emailBtn.enabled = false;
  }

Flex 4 - Email Validation

“register” State Validation

The register state is a combination of the above since we have the same textInput fields as we had in the first two section, just all in one state now.

Step 1. Changes to State Components

Change From:

<s:TextInput x="110" y="24" id="usernameTextInput2" text="{users.username}" includeIn="register"/>

Change To:

<s:TextInput x="110" y="24" id="usernameTextInput2" text="{users.username}" change="registerVal_changeHandler(event)" includeIn="register"/>

Change From:

<s:TextInput x="110" y="54" id="emailTextInput2" text="{users.email}" includeIn="register"/>

Change To:


<s:TextInput x="110" y="54" id="emailTextInput2" text="{users.email}" change="registerVal_changeHandler(event)" includeIn="register"/>

Change From:

<s:TextInput x="110" y="84" id="passwordTextInput2" text="{users.password}" displayAsPassword="true" includeIn="register"/>

Change To:

<s:TextInput x="110" y="84" id="passwordTextInput2" text="{users.password}" change="registerVal_changeHandler(event)" displayAsPassword="true" includeIn="register"/>

Change From:

<s:Button x="10" y="118" label="Save" id="saveBtn" click="saveBtn_clickHandler(event)" includeIn="register"/>

Change To:

<s:Button x="10" y="118" label="Save" id="saveBtn" click="saveBtn_clickHandler(event)" enabled="false" includeIn="register"/>

Step 2. Validation Function

protected function registerVal_changeHandler(event:TextOperationEvent):void
  {

  if (usernameTextInput2.text)
  {
  var valUsername2:ValidationResultEvent;
  usernameVal2.source = usernameTextInput2;
  usernameVal2.property = "text";
  usernameVal2.minLength=6;
  }

 if (emailTextInput2.text)
  {
  var valEmail2:ValidationResultEvent;
  emailVal2.source = emailTextInput2;
  emailVal2.property = "text";
  }

 if (passwordTextInput2.text)
  {
  var valPassword2:ValidationResultEvent;
  passwordVal2.source = passwordTextInput2;
  passwordVal2.property = "text";
  passwordVal2.minLength=6;
  }

 valUsername2 = usernameVal2.validate();
  valEmail2 = emailVal2.validate();
  valPassword2 = passwordVal2.validate();
  if(valUsername2.type == "valid" && valPassword2.type == "valid" && valEmail2.type == "valid")
  saveBtn.enabled = true;
  else
  saveBtn.enabled = false;
  }

Flex 4 - textInput and Email Validation

That’s it! Go ahead and save and run your application and check your validation in all three states. Make sure everything is working correctly. Your new application should look like:

<?xml version="1.0" encoding="utf-8"?>
  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  xmlns:s="library://ns.adobe.com/flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx"
  applicationComplete="init()"
  minWidth="955" minHeight="600" xmlns:valueObjects="valueObjects.*"
  xmlns:usersservice="services.usersservice.*">
  <fx:Script>
  <![CDATA[
  import mx.controls.Alert;
  import mx.events.ValidationResultEvent;
  import mx.rpc.events.ResultEvent;
  import mx.validators.EmailValidator;
  import mx.validators.StringValidator;

  import spark.events.TextOperationEvent;

  private var userid:int;
  private var usertype:String;

  private var usernameVal:StringValidator = new StringValidator();
  private var passwordVal:StringValidator = new StringValidator();

  private var emailVal:EmailValidator = new EmailValidator();

  private var usernameVal2:StringValidator = new StringValidator();
  private var emailVal2:EmailValidator = new EmailValidator();
  private var passwordVal2:StringValidator = new StringValidator();

  [Bindable]
  private var cookieAction:Boolean;

  protected function saveBtn_clickHandler(event:MouseEvent):void
  {
  var users2:Users = new Users();
  users2.username = usernameTextInput2.text;
  users2.email = emailTextInput2.text;
  users2.password = passwordTextInput2.text;
  users2.user_type = "user";

  createUsersResult.token = usersService.createUsers(users2);
  createUsersResult.token = usersService.commit();
  currentState = 'loggedOut';
  }

  private function checkLogin(event:ResultEvent):void
  {
  userid = event.result.loginsuccess;
  trace (userid);
  usertype = event.result.usertype;
  trace (usertype);
  cookieAction = event.result.usertype;
  trace (cookieAction);
  if (userid != 0)
  {
  currentState = usertype;
  }
  else
  {
  mx.controls.Alert.show('Invalid username/password');
  }
  }

  protected function createUsersResult_resultHandler(event:ResultEvent):void
  {
  mx.controls.Alert.show('Thank you for registering. You may login now!');
  currentState = "loggedOut";
  }

  private function init():void
  {
  getCookie.send();
  }

 protected function getCookie_resultHandler(event:ResultEvent):void
  {
  if(event.result.storedCookie == true)
  {
  cookieAction = true;
  username.text = event.result.creds.username;
  password.text = event.result.creds.password;
  loginBtn.enabled = true;
  }
  else
  {
  cookieAction == false;
  }
  }

  private function getPassword(event:ResultEvent):void
  {

  if(event.result.getPassword == "yes")
  {
  mx.controls.Alert.show('Your password has been emailed to you.');
  currentState = "loggedOut";
  }
  else
  {
  mx.controls.Alert.show('Invalid email, please try again.');
  }
  }

 protected function loggedOutVal_changeHandler(event:TextOperationEvent):void
  {

  if (username.text)
  {
  var valUsername:ValidationResultEvent;
  usernameVal.source = username;
  usernameVal.property = "text";
  usernameVal.minLength=6;
  }

  if (password.text)
  {
  var valPassword:ValidationResultEvent;
  passwordVal.source = password;
  passwordVal.property = "text";
  passwordVal.minLength=6;
  }

  valUsername = usernameVal.validate();
  valPassword = passwordVal.validate();
  if(valUsername.type == "valid" && valPassword.type == "valid")
  loginBtn.enabled = true;
  else
  loginBtn.enabled = false;
  }

 protected function email_toVal_changeHandler(event:TextOperationEvent):void
  {
  if (email_to.text)
  {
  var valEmail:ValidationResultEvent;
  emailVal.source = email_to;
  emailVal.property = "text";
  }

  valEmail = emailVal.validate();
  if(valEmail.type == "valid")
  emailBtn.enabled = true;
  else
  emailBtn.enabled = false;
  }

 protected function registerVal_changeHandler(event:TextOperationEvent):void
  {

  if (usernameTextInput2.text)
  {
  var valUsername2:ValidationResultEvent;
  usernameVal2.source = usernameTextInput2;
  usernameVal2.property = "text";
  usernameVal2.minLength=6;
  }

  if (emailTextInput2.text)
  {
  var valEmail2:ValidationResultEvent;
  emailVal2.source = emailTextInput2;
  emailVal2.property = "text";
  }

  if (passwordTextInput2.text)
  {
  var valPassword2:ValidationResultEvent;
  passwordVal2.source = passwordTextInput2;
  passwordVal2.property = "text";
  passwordVal2.minLength=6;
  }

  valUsername2 = usernameVal2.validate();
  valEmail2 = emailVal2.validate();
  valPassword2 = passwordVal2.validate();
  if(valUsername2.type == "valid" && valPassword2.type == "valid" && valEmail2.type == "valid")
  saveBtn.enabled = true;
  else
  saveBtn.enabled = false;
  }

 ]]>
  </fx:Script>
  <s:states>
  <s:State name="loggedOut"/>
  <s:State name="forgotPW"/>
  <s:State name="register"/>
  <s:State name="user"/>
  <s:State name="admin"/>
  </s:states>
  <fx:Declarations>
  <s:HTTPService id="login_user" result="checkLogin(event)" showBusyCursor="true" method="POST"
  url="login.php" useProxy="false">
  <s:request xmlns="">
  <username>
  {username.text}
  </username>
  <password>
  {password.text}
  </password>
  <logincookie>
  {setCookie.selected}
  </logincookie>
  </s:request>
  </s:HTTPService>

  <s:HTTPService id="getCookie" result="getCookie_resultHandler(event)" method="POST" url="getCookie.php"/>

  <mx:HTTPService id="get_password" result="getPassword(event)" showBusyCursor="true" method="POST"
  url="forgotPW.php" useProxy="false">
  <mx:request xmlns="">
  <email_to>
  {email_to.text}
  </email_to>
  </mx:request>
  </mx:HTTPService>

  <valueObjects:Users id="users"/>
  <usersservice:UsersService id="usersService" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)" showBusyCursor="true"/>
  <s:CallResponder id="createUsersResult" result="createUsersResult_resultHandler(event)"/>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
  </fx:Declarations>
  <s:Panel width="250" height="200" title="Flex 4 Login Box" horizontalCenter="0" verticalCenter="0">
  <s:Label x="10" y="18" text="Username" includeIn="loggedOut"/>
  <s:TextInput x="110" y="10" id="username" change="loggedOutVal_changeHandler(event)" includeIn="loggedOut"/>
  <s:Label x="12" y="47" text="Password" includeIn="loggedOut"/>
  <s:TextInput x="110" y="40" id="password" change="loggedOutVal_changeHandler(event)" displayAsPassword="true" includeIn="loggedOut"/>
  <s:Button x="10" y="72" id="loginBtn" label="Login" click="login_user.send();" enabled="false" includeIn="loggedOut"/>
  <s:Button x="120" y="72" label="Forgot Login Info?" click="currentState='forgotPW'" includeIn="loggedOut"/>
  <s:CheckBox x="10" y="101" label="Remember Me" id="setCookie" selected="{cookieAction}" includeIn="loggedOut"/>
  <s:Label x="195" y="103" text="Sign Up" click="currentState='register'" includeIn="loggedOut"/>

  <s:Label x="10" y="46" text="Email:" includeIn="forgotPW"/>
  <s:TextInput x="110" y="39" id="email_to" change="email_toVal_changeHandler(event)" includeIn="forgotPW"/>
  <s:Button x="8" y="72" id="emailBtn" label="Get Login Info" click="get_password.send();" enabled="false" includeIn="forgotPW"/>
  <s:Button x="168" y="72" label="&lt;&lt; Login" click="currentState='loggedOut'" includeIn="forgotPW"/>

  <s:Label x="10" y="31" text="Username:" includeIn="register"/>
  <s:TextInput x="110" y="24" id="usernameTextInput2" text="{users.username}" change="registerVal_changeHandler(event)" includeIn="register"/>
  <s:Label x="10" y="61" text="Email:" includeIn="register"/>
  <s:TextInput x="110" y="54" id="emailTextInput2" text="{users.email}" change="registerVal_changeHandler(event)" includeIn="register"/>
  <s:Label x="10" y="91" text="Password:" includeIn="register"/>
  <s:TextInput x="110" y="84" id="passwordTextInput2" text="{users.password}" change="registerVal_changeHandler(event)" displayAsPassword="true" includeIn="register"/>
  <s:Button x="10" y="118" label="Save" id="saveBtn" click="saveBtn_clickHandler(event)" enabled="false" includeIn="register"/>
  <s:Button x="168" y="118" label="&lt;&lt; Login" click="currentState='loggedOut'" includeIn="register"/>

  <s:Label x="10" y="10" text="Welcome User" includeIn="user"/>
  <s:Button x="10" y="30" label="Log Out" click="currentState='loggedOut'" includeIn="user"/>

  <s:Label x="10" y="10" text="Welcome Admin" includeIn="admin"/>
  <s:Button x="10" y="30" label="Admin Log Out" click="currentState='loggedOut'" includeIn="admin"/>
  </s:Panel>
  </s:Application>

About Dan Orlando

Dan Orlando is author of Flex 4 In Action and a recognized leader in the enterprise development community. As a long-time consultant, Dan's expertise on Adobe technology platforms is often called upon by industry leaders as well as publications such as IBM developerWorks, Adobe Developer Connection, and Amazon Web Services.
This entry was posted in ActionScript, Adobe, Flash, Flex, Flex 4, mySQL, php, RIA. Bookmark the permalink.

Comments are closed.