23
Sep
08

Setting focus in Flex using the Focus Manager

The following example shows how you can set focus on a TextInput control in Flex by using the Flex FocusManager class and the setFocus() method.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/23/setting-focus-in-flex-using-the-focus-manager/ -->
<mx:Application name="FocusManager_setFocus_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;

            private function submitButton_click(evt:MouseEvent):void {
                Alert.show(evt.currentTarget.label,
                            Object(focusManager.getFocus()).name);
            }

            private function resetButton_click(evt:MouseEvent):void {
                username.text = "";
                password.text = "";
                Alert.show(evt.currentTarget.label,
                            Object(focusManager.getFocus()).name);
            }
        ]]>
    </mx:Script>

    <mx:ApplicationControlBar dock="true">
        <mx:Button label="Set focus to Username"
                click="focusManager.setFocus(username);" />
        <mx:Button label="Set focus to Password"
                click="focusManager.setFocus(password);" />
    </mx:ApplicationControlBar>

    <mx:Form id="form"
            defaultButton="{submitButton}">
        <mx:FormItem label="Username:">
            <mx:TextInput id="username" />
        </mx:FormItem>
        <mx:FormItem label="Password:">
            <mx:TextInput id="password"
                    displayAsPassword="true" />
        </mx:FormItem>
        <mx:FormItem direction="horizontal"
                horizontalAlign="right"
                width="100%">
            <mx:Button id="submitButton"
                    label="Submit"
                    click="submitButton_click(event);" />
            <mx:Button id="resetButton"
                    label="Reset"
                    click="resetButton_click(event);" />
        </mx:FormItem>
    </mx:Form>

</mx:Application>

View source is enabled in the following example.

Due to popular demand, here is the “same” example in a more ActionScript friendly format:

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/23/setting-focus-in-flex-using-the-focus-manager/ -->
<mx:Application name="FocusManager_setFocus_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white"
        initialize="init();">

    <mx:Script>
        <![CDATA[
            import mx.containers.ApplicationControlBar;
            import mx.containers.Form;
            import mx.containers.FormItem;
            import mx.containers.FormItemDirection;
            import mx.controls.Alert;
            import mx.controls.Button;
            import mx.controls.TextInput;

            private var usernameButton:Button;
            private var passwordButton:Button;
            private var username:TextInput;
            private var password:TextInput;
            private var submitButton:Button;
            private var resetButton:Button;

            private function init():void {
                usernameButton = new Button();
                usernameButton.label = "Set focus to Username";
                usernameButton.addEventListener(MouseEvent.CLICK,
                            usernameButton_click);

                passwordButton = new Button();
                passwordButton.label = "Set focus to Password";
                passwordButton.addEventListener(MouseEvent.CLICK,
                            passwordButton_click);

                var appControlBar:ApplicationControlBar;
                appControlBar = new ApplicationControlBar();
                appControlBar.dock = true;
                appControlBar.addChild(usernameButton);
                appControlBar.addChild(passwordButton);
                addChildAt(appControlBar, 0);

                username = new TextInput();
                username.name = "username";

                password = new TextInput();
                password.displayAsPassword = true;
                password.name = "password";

                submitButton = new Button();
                submitButton.label = "Submit";
                submitButton.name = "submitButton";
                submitButton.addEventListener(MouseEvent.CLICK,
                            submitButton_click);

                resetButton = new Button();
                resetButton.label = "Reset";
                resetButton.name = "resetButton";
                resetButton.addEventListener(MouseEvent.CLICK,
                            resetButton_click);

                var formItem1:FormItem = new FormItem();
                formItem1.label = "Username:";
                formItem1.addChild(username);

                var formItem2:FormItem = new FormItem();
                formItem2.label = "Password:";
                formItem2.addChild(password);

                var formItem3:FormItem = new FormItem();
                formItem3.direction = FormItemDirection.HORIZONTAL;
                formItem3.setStyle("horizontalAlign", "right");
                formItem3.percentWidth = 100;
                formItem3.addChild(submitButton);
                formItem3.addChild(resetButton);

                var form:Form = new Form();
                form.defaultButton = submitButton;
                form.addChild(formItem1);
                form.addChild(formItem2);
                form.addChild(formItem3);
                addChild(form);
            }

            private function usernameButton_click(evt:MouseEvent):void {
                focusManager.setFocus(username);
            }

            private function passwordButton_click(evt:MouseEvent):void {
                focusManager.setFocus(password);
            }

            private function submitButton_click(evt:MouseEvent):void {
                Alert.show(evt.currentTarget.label,
                            Object(focusManager.getFocus()).name);
            }

            private function resetButton_click(evt:MouseEvent):void {
                username.text = "";
                password.text = "";
                Alert.show(evt.currentTarget.label,
                            Object(focusManager.getFocus()).name);
            }
        ]]>
    </mx:Script>

</mx:Application>

18 Responses to “Setting focus in Flex using the Focus Manager”


  1. 1 Inca Sep 23rd, 2008 at 11:44 pm

    Another nice, clean example but… there are loads of issues with the FocusManager. In fact, it rarely works as you would expect and definitely not as your simple example implies. It’s very difficult to set the focus when a .swf loads and the ‘I-Beam’ caret and where you actually are on the page constantly gets out of sync, confusing users.

    All in all, it is very broken except in the simplest circumstances so before you try and implement it tyry Googling for “Flex setfocus problem” and see what you will be up against.

  2. 2 peterd Sep 24th, 2008 at 7:33 am

    And as a reminder, if you do encounter bugs with the Flex SDK (or Flex Builder, Flex Documentation, Flash Player, etc), the best place to report them is http://bugs.adobe.com/flex/ .

    Peter

  3. 3 time2design Oct 6th, 2008 at 1:32 pm

    This is a great example but what would you do to make a TextInput field have focus by default?

  4. 4 peterd Oct 6th, 2008 at 11:48 pm

    time2design,

    I think something like this should work:

    <mx:Application name="FocusManager_setFocus_test"
            xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="vertical"
            verticalAlign="middle"
            backgroundColor="white"
            creationComplete="focusManager.setFocus(username);">
    

    Peter

  5. 5 OneWorldMedia Nov 9th, 2008 at 4:27 pm

    You would think this would work but it was unsuccessful for me… I’m only able to set the focus on a text input box by firing it off via a button push. The creation complete doesn’t do it. Very frustrating. And it’s not even the main form in my application so the swf already received focus (I’m using a togglebuttonbar and a viewstack and the text input is on a form that displays after pushing a menu option on the togglebuttonbar) … not sure why the creation complete doesn’t work.

    Ken

  6. 6 Terroso.Costa Jan 26th, 2009 at 2:50 am

    Hi OneWorldMedia, try to use the show() method instead of creationcomplete.

    Cheers,

    Rui

  7. 7 ra Feb 8th, 2009 at 7:01 pm

    Hi Terroso.Costa, I have tried to use to the show() method instead of creationcomplete. But not success.

  8. 8 ropo Feb 9th, 2009 at 3:03 am

    show() did not work for me.

    tinput.addEventListener(FlexEvent.UPDATE_COMPLETE, focus);
    
    public function focus(event:Event):void {
        var ti:TextInput = TextInput(event.currentTarget);
        ti.focusManager.setFocus(ti);
    }
    
  9. 9 jurlan Mar 14th, 2009 at 4:31 am

    FocusManager works half for me ..
    It does light up the border around my TextInput but the cursor is not blinking inside nor can I type before actually clicking in the TextInput. This is with use of creationcomplete().
    Show() does nothing :(

  10. 10 Larry Mar 26th, 2009 at 1:50 pm

    Hello,

    One work around for setting initial focus is to manually dispatch an event, like mouse click, then have the event handler set the focus.

    I ran into a tough spot when using the mouse over event to set focus. If you mouse over a component and a wipe plays, when the wipe “reveals” what is underneath, the target/current target becomes what is revealed. When the wipe effect completes, the “curtain” gets the focus again.

    So, in my case, I had to do this:
    var myPoint:Point = new Point();
    myPoint.x = stage.mouseX;
    myPoint.y = stage.mouseY;
    var i:int = (stage.getObjectsUnderPoint(myPoint).length);

    if ( InteractiveObject(stage.getObjectsUnderPoint(myPoint)[i-1].parent).toString()
    !=
    this.toString()
    )
    {
    trace(”setting focus”);
    stage.focus=InteractiveObject(stage.getObjectsUnderPoint(myPoint)[i-1].parent);
    }

    I am relatively new to Flex development, so I do not know if this approach is “good”, but it works!

    Hope this helpls.

    Larry

  11. 11 Larry Mar 26th, 2009 at 1:52 pm

    I am sorry, this is wrong:
    the “curtain” gets the focus again.

    what happens is that the curtain DOES NOT get the focus again. Which is why I had to fire set the focus manually. Otherwise, the subsequent keyboard stroke, which depends on focus, does not occur.

  12. 12 Larry Mar 27th, 2009 at 3:33 pm

    Hello Everyone,

    As this blog has really help me so very much in improving my development skills, I wanted to take the time to solve this issue.

    Here is the solution:

  13. 13 Larry Mar 27th, 2009 at 3:34 pm
    //Set the focus to the Text input field.
    private function setFocusOnStart(event:Event):void
    {
        stage.focus=InteractiveObject(myTextInput);
    }
    
  14. 14 Bryan Clover Apr 7th, 2009 at 6:50 am

    If you want to create a login control that has focus and is waiting for user input when your application firsts starts, there are a few things you need to do.

    1. Inside the HTML page that serves up your SWF file, create a Javascript function that will automatically give the SWF movie focus, and call it from Flex using the ExternalInterface. This is necessary to give the SWF focus in both FireFox and Internet Explorer.

    2. Set focus to the TextInput component. This highlights your TextInput component.

    3. Set the selectionBeginIndex and selectionEndIndex to 0. This puts the cursor in the TextInput control and allows the user to just start typing.

    ********************************************
    So here’s the code to make this all happen!
    ********************************************

    1. Create a Javascript function inside your index.template.html or HTML wrapper file that holds your SWF.

    <script language="JavaScript" type="text/javascript" >
    <!--
    function setFocus()
    {
        window.document.FuelMasterSite.focus();
    }
    
    // -->
    </script>
    

    NOTE: Replace FuelMasterSite with the name of your SWF movie.

    2. Create the MXML Code that will fire an init() method when your application is done loading.

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init(event)" >
    
        <mx:TextInput id="TXI_UserName" />
        <mx:TextInput id="TXI_Password" />
    
    </mx:Application>
    

    3. Create the init() method in Actionscript:

    import flash.external.ExternalInterface;
    import mx.controls.Alert;
    
    private const EMPTY_STRING:String = '';
    
    private function init(event:Event):void {
        if (ExternalInterface.available) {
            ExternalInterface.call('setFocus');
        } else {
            Alert.show("Browser not available");
        }
        focusManager.setFocus(TXI_UserName);
        TXI_UserName.text = EMPTY_STRING;
        TXI_Password.text = EMPTY_STRING;
        LBL_Feedback.text = EMPTY_STRING;
        TXI_UserName.selectionBeginIndex = 0;
        TXI_UserName.selectionEndIndex = TXI_UserName.text.length;
    }
    
  15. 15 Chris Apr 11th, 2009 at 12:40 pm

    Hi Bryan

    Thanks for this. Your solution worked for me.

    Seems like a lot of lines of code to do what you’d think would be a fairly simple task.

    Another thing I thought I’d - I was having trouble getting it to work until I removed the space you had between “<” and “script” in the JavaScript declaration in step 1. Just something that might also trip up other people….

  16. 16 Tim May 7th, 2009 at 7:36 am

    This works fin in Firefox and IE7, however, it does not work in Safari or Chrome.

    Does anyone know how the script can be changed to cater for these browsers.

  17. 17 Acatl May 18th, 2009 at 3:26 pm

    (ups last post has an error sorry)

    ExternalInterface did not do the job for me, but using navitageToURL did:

    AS3 code

    private function onCreationComplete(event:FlexEvent):void
    {
    // - - all code related to focus of a specific component place it here - -

    var u:URLRequest = new URLRequest(”javascript:focusFlexApp()”);
    navigateToURL(u,”_self”);
    }

    Javascript code on ‘index.template.html’

    function focusFlexApp()
    {
    var app = document.getElementById(’${application}’);
    app.focus();
    }

  18. 18 Arnold Aprieto Jun 3rd, 2009 at 1:05 pm

    Thanks Bryan. Your solution is exactly what I was looking for.

Leave a Reply

This blog is terrible at eating HTML tags. If you plan on posting code/XML, please escape your "<" characters as "&lt;" and your ">" characters as "&gt;".




September 2008
M T W T F S S
« Aug   Oct »
1234567
891011121314
15161718192021
22232425262728
2930  

Badge Farm

  • Powered by Redoable 1.2
  • Cornify
  • Feeds burnt by Feedburner
  • Feed