Select text on input focus

102,458

Solution 1

The way to do this in Angular is to create a custom directive which does the autoselect for you.

module.directive('selectOnClick', ['$window', function ($window) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function () {
                if (!$window.getSelection().toString()) {
                    // Required for mobile Safari
                    this.setSelectionRange(0, this.value.length)
                }
            });
        }
    };
}]);

Apply the directive like this:

<input type="text" value="test" select-on-click />

View demo

Update1: Removed jQuery dependency.

Update2: Restrict as attribute.

Update3: Works in mobile Safari. Allows selecting part of the text (requires IE>8).

Solution 2

Here's an enhanced directive which avoids reselecting the text when the user clicks to position the cursor in the input box.

module.directive('selectOnClick', function () {
    return {
        restrict: 'A',
        link: function (scope, element) {
            var focusedElement;
            element.on('click', function () {
                if (focusedElement != this) {
                    this.select();
                    focusedElement = this;
                }
            });
            element.on('blur', function () {
                focusedElement = null;
            });
        }
    };
})

Solution 3

This is an old answer, for Angular 1.x

Better way to do it is by using the ng-click built-in directive:

<input type="text" ng-model="content" ng-click="$event.target.select()" />

EDIT:

As JoshMB has kindly reminded; referencing DOM nodes in Angular 1.2+ is no longer allowed. So, I've moved $event.target.select() into the controller:

<input type="text" ng-model="content" ng-click="onTextClick($event)" />

Then in your controller:

$scope.onTextClick = function ($event) {
    $event.target.select();
};

Here is an example fiddle.

Solution 4

Neither of proposed solutions worked well for me. After quick research I came up with this:

module.directive('selectOnFocus', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var focusedElement = null;

            element.on('focus', function () {
                var self = this;
                if (focusedElement != self) {
                    focusedElement = self;
                    $timeout(function () {
                        self.select();
                    }, 10);
                }
            });

            element.on('blur', function () {
                focusedElement = null;
            });
    }

  }

});

It's a mix of several solutions proposed, but works both on click and focus (think autofocus) and allows manual selection of partial value in the input.

Solution 5

For me, ng-click didn't have sense, because you could never reposition the cursor without selecting all text again, I found this was annoing. Then it is better to use ng-focus, because the text is selected only if the input was not focused, if you click again to reposition the cursor then the text just deselects, as expected, and you can write in between.

I found this approach to be the expected UX behaviour.

Use ng-focus

Option 1: separate code

<input type="text" ng-model="content" ng-focus="onTextFocus($event)" />

and in controller

$scope.onTextFocus = function ($event) {
  $event.target.select();
};

Option 2: as an alternative you can join the code above into this "one-liner" (I didn't test this but it should work)

<input type="text" ng-model="content" ng-focus="$event.target.select()" />
Share:
102,458
Billy Coover
Author by

Billy Coover

CEO at Nearby Now

Updated on July 08, 2022

Comments

  • Billy Coover
    Billy Coover almost 2 years

    I have a text input. When the input receives focus I want to select the text inside of the input.

    With jQuery I'd do it this way:

    <input type="text" value="test" />
    
    $("input[type=text]").click(function() {
        $(this).select();
        // would select "test" in this example
    });
    

    I've searched around to try and find the Angular way but most examples I'm finding are dealing with a directive that is watching a modal property for a change. I'm assuming I need a directive that is watching for an input that receives focus. How would I do that?

  • jack
    jack almost 11 years
    If you want to do this without jquery, change element.click to element.bind('click', function() { ... } and element.select() to element[0].select()
  • Eliran Malka
    Eliran Malka over 10 years
    Nice and elegant. I would also explicitly restrict the directive to be applied as attribute (by returning an object literal and setting restrict: 'A'), as this directive aims for extending the behavior of an existing element.
  • JoshMB
    JoshMB about 10 years
    As far as I can tell, this no longer supported. Angular throws an error: "Referencing DOM nodes in Angular expressions is disallowed!". See this thread for more info: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4. The directive approach works well, however.
  • Onur Yıldırım
    Onur Yıldırım about 10 years
    You're right. This is the case for Angular 1.2+. I'll update the answer.
  • Vladimir Gordienko
    Vladimir Gordienko over 9 years
    I think this answer is better than the accepted, because it allow set cursor to some position in entered text, but, as a directive have own scope - i propose to rename focusedElement variable to isElementFocused and store there true or false
  • Piioo
    Piioo over 9 years
    DOM changes should be done in the directive, or not?
  • Precastic
    Precastic over 9 years
    For some reason the other solutions didn't work for me but this did. I think the problem was that I already had a directive on the element which I was adding this click event to.
  • Dzmitry Lazerka
    Dzmitry Lazerka over 9 years
    @Martin any idea how to do that on page open, without user click? The problem is that default value is set in another controller before my selectOnLoad directive link(). But in link(), although scope is already populated, element DOM is not yet synced with $scope, so when I call select(), element is still empty and nothing selected. The only way to work around that I found, is $timeout, but I feel that can stop working with some new Angular version.
  • Robbie Smith
    Robbie Smith over 9 years
    I get Uncaught TypeError: undefined is not a function on "this" for .select(); and yes jQuery 1.9.1 is included.
  • jcalfee314
    jcalfee314 over 9 years
    Seriously, even the onTextClick($event) is throwing the error now. Aside from the un-intuitive nature of this beast, how much is this inconvenience costing us in performance?
  • jcalfee314
    jcalfee314 over 9 years
    I'm giving up .. my angularjs app is going to be harder to use.
  • ak85
    ak85 over 9 years
    this works well on desktop/android but when I try on ipad it doesn't seem to work. Is there a known work around here?
  • Abraham Chan
    Abraham Chan about 9 years
  • user1338062
    user1338062 about 9 years
    In Firefox 38.0.5 clicking in the middle of the text first selects all, but then removes the selection, so this won't work.
  • user1338062
    user1338062 about 9 years
    This seems the best way to go, but unfortunately it prevents selecting part of the text.
  • infomofo
    infomofo over 8 years
    I still had significant issues getting this to work on mobile safari. For one, the sample code only listens for "click" events and on mobile safari, the events are "touchstart" and "touchend". I also had issues with the automatic focusing causing the selection to end, so I had to prevent default behavior on touchend. Here's my modified version of the directive. gist.github.com/infomofo/4e9828fbd886eeb226a8
  • Blackfire
    Blackfire over 8 years
    Syntax error corrected: last }); replace by: } }; });
  • Louis
    Louis about 8 years
    This one works for input type="number", which is great ! Thanks
  • Louis
    Louis about 8 years
    Hey, this works for Ionic in Android, but not in iOS...any idea why ? Thanks
  • Adam Reis
    Adam Reis almost 8 years
    Note that this won't work on <input type='number'>, see: stackoverflow.com/questions/21177489/…
  • Langdon
    Langdon over 7 years
    Seems like you left some code behind when you adapted it from onClick... what's the point of focusedElement?
  • Langdon
    Langdon over 7 years
    This probably isn't going to ever work consistently without delaying this.select.
  • pistol-pete
    pistol-pete over 7 years
    Simple and it works. This also allows for positioning of your cursor within the selected text, as discussed above.
  • mtfurlan
    mtfurlan about 7 years
    Using ng-focus allows a user to select subsets if they really want to.
  • Lex
    Lex over 6 years
    @RobbieSmith I'm 3 years late, but change all instances of this to element[0] and it should work. I also recommend changing click to focus so that text will be selected if the user tabs into the input instead of clicking into it.
  • Claudio Ferraro
    Claudio Ferraro about 5 years
    On angular 6 it's almost the same: Only replace ng-click with (click)="onTextClick($event); and in Your component onTexclick = function($event) { ...}
  • SwissCoder
    SwissCoder over 4 years
    how come so many people come up with all these complex answers, when the easiest way is here :D Thank you Adam
  • Eagle
    Eagle almost 4 years
    Again, simplicity is the best over complexity. You follow KISS, you win. ;)