What is the 'Angular way' to set focus on input field in AngularJS?
More specific requirements:
- When a Modal is opened, set focus on a predefined
<input>
inside this Modal. - Everytime
<input>
becomes visible (e.g. by clicking some button), set focus on it.
I tried to achieve the first requirement with autofocus
, but this works only when the Modal is opened for the first time, and only in certain browsers (e.g. in Firefox it doesn't work).
Any help will be appreciated.
I've written a two-way binding focus directive, just like model recently.
You can use the focus directive like this:
If you make someFocusVariable scope variable
true
in anywhere in your controller, the input get focused. And if you want to "blur" your input then, someFocusVariable can be set to false. It's like Mark Rajcok's first answer but with two-way binding.Here is the directive:
Usage:
Here is the fiddle:
http://fiddle.jshell.net/ubenzer/9FSL4/8/
If you wish to set focus on particular element, you can use below approach.
Create a service called
focus
.Inject it into the controller from where you wish to call.
Call this service.
Instead of creating your own directive, it's possible to simply use javascript functions to accomplish a focus.
Here is an example.
In the html file:
In a file javascript, in a controller for example, where you want to activate the focus:
(EDIT: I've added an updated solution below this explanation)
Mark Rajcok is the man... and his answer is a valid answer, but it
hashad a defect (sorry Mark)......Try using the boolean to focus on the input, then blur the input, then try using it to focus the input again. It won't work unless you reset the boolean to false, then $digest, then reset it back to true. Even if you use a string comparison in your expression, you'll be forced to change the string to something else, $digest, then change it back.(This has been addressed with the blur event handler.)So I propose this alternate solution:
Use an event, the forgotten feature of Angular.
JavaScript loves events after all. Events are inherently loosely coupled, and even better, you avoid adding another $watch to your $digest.
So now you could use it like this:
and then anywhere in your app...
This is awesome because you can do all sorts of things with something like this. For one, you could tie into events that already exist. For another thing you start doing something smart by having different parts of your app publish events that other parts of your app can subscribe to.
Anyhow, this type of thing screams "event driven" to me. I think as Angular developers we try really hard to hammer $scope shaped pegs into event shape holes.
Is it the best solution? I dunno. It's a solution.
Updated Solution
After @ShimonRachlenko's comment below, I've changed my method of doing this slightly. Now I use a combination of a service and a directive that handles an event "behind the scenes":
Other than that, it's the same principal outlined above.
Here is a quick demo Plunk
Usage
Source
First, an official way to do focus is on the roadmap for 1.1. Meanwhile, you can write a directive to implement setting focus.
Second, to set focus on an item after it has become visible currently requires a workaround. Just delay your call to element focus() with a
$timeout
.Because the same controller-modifies-DOM problem exists for focus, blur and select, I propose having an
ng-target
directive:Angular thread here: http://goo.gl/ipsx4 , and more details blogged here: http://goo.gl/4rdZa
The following directive will create a
.focus()
function inside your controller as specified by yourng-target
attribute. (It creates a.blur()
and a.select()
too.) Demo: http://jsfiddle.net/bseib/WUcQX/For those who use Angular with the Bootstrap plugin:
http://angular-ui.github.io/bootstrap/#/modal
You can hook into the
opened
promise of the modal instance: