Scenario: You need to validate user input in a TextInput component for legal values.
Solution : Use the 'textInput' event to intercept the characters a users types before they are committed and cancel the committing of the character if it is illegal.
Explanation:
There could be times when you want to restrict what a user types into a TextInput component but the restrict property isn’t good enough. Two examples of this would be to filter out restricted words or validate a numeric input against a minimum and/or maximum value. The way to do this is to add an event listener to the ‘textInput’ event that the component dispatches as the user types.
The TextInput component dispatches 2 events as the user types – a 'textInput' event and a 'change' event. The difference in the 2 events is when they are dispatched. The 'textInput' event is dispatched when the text is changed through typing or pasting characters into the text field but before that text is committed to the text property. The change event is dispatched after the text has been committed. The ‘textInput’ event is also a cancellable event. A cancelable event is one that can be stopped by calling event.preventDefault().
The TextInput component has a internal text field that dispatches a ‘textInput’ event that the TextInput component listens for. It then modifies the event by making it cancellable and re-dispatches it. Because of the way events flow through the display list the event handler in the TextInput component is called before the same handler in the internal text field. This allows us to cancel the event before it reaches the internal text field and stop the text from being committed.
This is the event handler in the TextInput component.
private function textField_textInputHandler(event:TextEvent):void
{
event.stopImmediatePropagation();
// Dispatch a cancelable version of this event.
var newEvent:TextEvent =
new TextEvent(TextEvent.TEXT_INPUT, false, true);
newEvent.text = event.text;
dispatchEvent(newEvent);
// If any handler has called preventDefault(),
// then stop the TextField from accepting the text.
if (newEvent.isDefaultPrevented())
event.preventDefault();
}
As you can see from the code at the end - if the event that was dispatched by this component is canceled then the event that this method received is also canceled.
So how do we cancel this event? This is up to the developer to add an event listener to the TextInput component and use the handler to validate the input and call event.preventDefault() validation fails.
A working example – validating a numerical value against a minimum and maximum value:
<mx:TextInput id="lengthInput"
width="40"
restrict="0-9">
<mx:textInput>
<![CDATA[
var text:String = TextInput(event.target).text + event.text;
if(text.length > 0)
{
var value:Number = parseInt(text);
if(value < minimumValue || value > maximumValue)
{
event.preventDefault();
}
}
]]>
</mx:textInput>
</mx:TextInput>
In the above code the restrict property on the TextInput component is set to only allow numbers. In the handler for the ‘textInput’ event we get the text string sent in the event (the event only sends the text that changed not the text that has been committed) and append it to the text that has already been committed. We then check to make sure it is not empty and then convert it to a number and validate it against a minimum and maximum value. If it fails validation we cancel the event and stop the last character(s) entered from being committed.
As noted above this method can be used anytime you want to validate user input before that input is committed. You could also use this event to display an error message if validation fails.
Comments
Re: Flex Examples : Validating user input in a TextInput ...
Hmm... Before a Developer commits to using this technique, I would strongly recommend considering its impact on usability.
In actual usability testing, I have seen overly-aggressive validation introduce new problems (at least for Users), despite its general attractiveness (at least for the Developer).
In this case, you may find that your users are confused when characters that they (thought?) they typed don't actually appear in the field. Or they may think that your application is 'broken'--perhaps not the impression that you want them to have.
You may want to consider not triggering the validation check until later in the work flow. By 'later' I mean a time such as the following: upon form submittal; when focus leaves the field; or AFTER the illegal character has been echoed and is visible to the user. As a broad rule, waiting until form submittal is usually later than is desirable (from a usability standpoint), but validating before character echo is usually earlier than is desirable. Typically, on echo or on field losing focus is best.
The one scenario in which I sometimes do use early triggers (such as the textInput event), is when I have a rigidly-formatted, masked input field (such as a US Social Security Number field with hyphen ('-') masks. In that case, I use it to allow users to enter the hyphen characters, but filter them out from the field's value.
===============
Sense or Non-sense?
Re: Flex Examples : Validating user input in a TextInput ...
While I agree that overly-aggressive validation can be a problem I think validating too late is a worse solution. In this case I think the best solution would be to present an error tip to the user if they typed in an invalid character. You could have an error tip fade in for a few seconds and then fade out immediately when a valid character is entered. Of course giving the user some sort of hint as to what characters are valid is probably a good thing to do.
For your example with the social security field I use this component http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&ex.... It extends TextInput to allow the developer to specify a mask for the input.