views:

57

answers:

3

What TextInput event can I listen for to throw an Alert when a number is entered? The scenario is : a user enters a number into myTxt1. An Alert appears that says "Are you sure you want to enter that number?". If the user clicks Yes, do nothing/continue. If the user clicks No, leave focus on myTxt1 so he can change the number.

Problem is, I don't know what event to listen to to throw the Alert. I've tried valueCommit and focusOut. With both of these, the alert shows, but when the user clicks Yes, focus remains on myTxt1, even if the event was triggered by the user clicking on myTxt2. User tries to leave myTxt1, but sees the ALert, clicks Yes, focus remains on myTxt1, and it's a vicious cycle.

This seems like a simple issue, but I can't figure it out. Any advice?

+2  A: 

If you are trying to prevent user from entering numbers or otherwise consider using restrict property. But if you just want user to be notified for entering number, you may use change event.

Faheem
+1  A: 

In your focusOut handler you have to store the object that is going to get the focus. That's because when you show an Alert this information is gone since the Alert window now gets the focus. See the following example on how to do it properly. I'd suggest you build your own custom component that does all the work for you...

<?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">

    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.CloseEvent;
            import mx.managers.FocusManager;

            protected var previousValue:String;
            protected var nextValue:String;
            protected var focusInObject:InteractiveObject;

            protected function isNumber(value:String):Boolean
            {
                // do your check
                return true;
            }

            protected function textInput_focusOutHandler(event:FocusEvent):void
            {
                var value:String = TextInput(event.currentTarget).text;

                if (!isNumber(value) || value == previousValue)
                    return;

                nextValue = value;
                focusInObject = event.relatedObject;
                Alert.show("Are you sure you want to enter that number?", "", Alert.YES | Alert.NO, this, alertCloseHandler);
            }

            protected function alertCloseHandler(event:CloseEvent):void
            {
                if (event.detail == Alert.NO)
                    return;

                previousValue = nextValue;

                if (focusInObject)
                    systemManager.stage.focus = focusInObject;
            }
        ]]>
    </fx:Script>

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

    <s:TextInput focusOut="textInput_focusOutHandler(event)"/>

    <s:CheckBox label="Foo"/>
    <s:Button label="Bar"/>
</s:Application>

I've included a small optimization. The application remembers the value if the user presses Yes. In case you get another focusOut event and the value hasn't changed since last time then the Alert won't be shown.

Gerhard
Thank you Gerhard! This is exactly the solution that I'm looking for, but (big but), I can't make it work with my code. I've got a number of TextInput controls that the user will tab or click through to enter a series of numbers. When I add another TextInput to your code, then enter a number in the first and click on the second, I run into a problem in the focusOutHandler. I'm looking at the 'focusInObject = ... " line. ALthough event.relatedObject looks good, focusInObject is set to null. It seems there's a problem attaching the IFocusManagerComponent interface to a TextInput.
Carrie
Do you know a workaround? Here's the code I'm working with (edited a bit to so I could run it as a Flex app)
Carrie
Sorry, I can't paste in my code bc it's too long, but I just added a second TextInput after your first one.
Carrie
Ah, I see. I didn't notice that bug since it seems to happen only with `mx:TextInput`. Well, I've revised my code sample. I'm storing the `event.relatedObject` now without casting and set the focus directly with `systemManager.stage.focus = focusInObject;`
Gerhard
Thanks a ton, Gerhard! I think this does the trick!
Carrie
A: 

You can listen for the change event if its a TextArea component. If there is any change in the text area then a change event will be fired. You can then check which key is pressed.

jase21