Billy Coover
Billy Coover

Reputation: 3837

Select text on input focus

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?

Upvotes: 122

Views: 106235

Answers (11)

Niamatullah Bakhshi
Niamatullah Bakhshi

Reputation: 1579

$event.target.select() not resolved in Angular template

The event target can be any HTML Element and a cast to the application interface should be applied here (like HTMLSelectElement), however, Angular expressions don't allow casting. The best workaround would be to wrap $event.target with $any()

so, it should look like this: (focus) = $any($event.target).select()

further explanation found here here.

Upvotes: -1

Dan Ortega
Dan Ortega

Reputation: 1909

The easiest way to select all text on click or focus or tab, is !!!:

<input (focus)="inputFocused($event)">

...

inputFocused(event: any){
    event.target.select()
}

Upvotes: 3

Adam Reis
Adam Reis

Reputation: 4483

No directives needed, just add onfocus="this.select()" native javascript to the input element or text area.

Upvotes: 11

Onur Yıldırım
Onur Yıldırım

Reputation: 33674

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.

Upvotes: 42

user2456016
user2456016

Reputation:

In angular 2, this worked for me, both in Chrome & Firefox:

<input type="text" (mouseup)="$event.target.select()">

Upvotes: 8

jperelli
jperelli

Reputation: 7207

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()" />

Upvotes: 12

Ola
Ola

Reputation: 1

Modified version that worked for me. First click selects text, second click on same element deselects text

module.directive('selectOnClick', function ($timeout) {
return {
    restrict: 'A',
    link: function (scope, element, attrs) {
        var prevClickElem = null; //Last clicked element
        var ignorePrevNullOnBlur = false; //Ignoring the prevClickElem = null in Blur massege function

        element.on('click', function () {
            var self = this;
            if (prevClickElem != self) { //First click on new element
                prevClickElem = self; 
                $timeout(function () { //Timer
                    if(self.type == "number")
                        self.select();
                    else
                        self.setSelectionRange(0, self.value.length)
                }, 10);
            }
            else { //Second click on same element
                if (self.type == "number") {
                    ignorePrevNullOnBlur = true;
                    self.blur();
                }
                else
                    self.setSelectionRange(self.value.length, self.value.length); //deselect and set cursor on last pos
            }
        });

        element.on('blur', function () {
            if (ignorePrevNullOnBlur == true)
                ignorePrevNullOnBlur = false; //blur called from code handeling the second click 
            else
                prevClickElem = null; //We are leaving input box
        });
    }
}

})

Upvotes: 0

xaralis
xaralis

Reputation: 4774

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.

Upvotes: 15

Martin
Martin

Reputation: 8866

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).

Upvotes: 217

OrangeKing89
OrangeKing89

Reputation: 704

The accepted answer is using the click event however if you use the focus event, only the 1st click will fire the event and it also fires when some other method is used to focus on the input (like hitting tab or calling focus in code).

This also makes it unnecessary to check if the element is already focused as Tamlyn's answer suggests.

app.directive('selectOnClick', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('focus', function () {
                this.select();
            });
        }
    };
});

Upvotes: 6

Tamlyn
Tamlyn

Reputation: 23602

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;
            });
        }
    };
})

Upvotes: 44

Related Questions