Select text on input focus
AngularjsAngularjs DirectiveAngularjs Problem Overview
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?
Angularjs Solutions
Solution 1 - Angularjs
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 />
Update1: Removed jQuery dependency.
Update2: Restrict as attribute.
Update3: Works in mobile Safari. Allows selecting part of the text (requires IE>8).
Solution 2 - Angularjs
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 - Angularjs
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 - Angularjs
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 - Angularjs
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()" />
Solution 6 - Angularjs
No directives needed, just add onfocus="this.select()"
native javascript to the input element or text area.
Solution 7 - Angularjs
In angular 2, this worked for me, both in Chrome & Firefox:
<input type="text" (mouseup)="$event.target.select()">
Solution 8 - Angularjs
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();
});
}
};
});
Solution 9 - Angularjs
The easiest way to select all text on click or focus or tab, is !!!:
<input (focus)="inputFocused($event)">
...
inputFocused(event: any){
event.target.select()
}
Solution 10 - Angularjs
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
});
}
}
})
Solution 11 - Angularjs
$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.