You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
Repository navigation
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
Listening for focus/blur events is nice, but it frequently comes up that I need to set the focus on a certain element. E.g. clicking an "add comment" button opens up text field and sets focus inside the textarea. Clicking submit/cancel closes the form and puts focus back on the "add comment" button.
My initial thought was ng-focus-model="some.model". Setting some.model to true in the controller would then move focus to the element. But after experimenting with this, I've found that to be pretty unintuitive. This is one of the few cases where reaching into the DOM and just calling element.focus() seems like the right thing to do. Perhaps angular could provide a way to access dom elements from controllers (heresy!!) but with a severly limited API (i.e. only supports focus())
There has been quite some discussion around this topic, so a proper solution requires more effort no doubt, but I thought I'd share the following which has served me well so far.
Sounds like my implementation is similar to that of @ewinslow's, the only real difference being syntax; "focus-model" to me implies it should only watch model properties, whereas I usually have a $scope.state object separate to my $scope.form model.
I opted for "focus-when", but I suppose ng-autofocus might fit better with Angular's motto "HTML enhanced"; adding the attribute autofocus to the element when ng-autofocus evaluates to true, similar to how ng-required works..
The spirit of the addition, at this point, is that I'm implementing a new controller, similar to an NgModelController, but seperate, as it only worries about managing focus. More details can be found at the link.
$timeout or setTimeout works great indeed, but not so on mobile safari. You have to set the focus inside the event loop of ngClick in order for focus to work properly on iOS (triggering the keyboard), so any timeouts are off limits. I've looked around but found no mention of this problem anywhere, I can't imagine no one else encountered this yet though...
The only way to go around this is by using event listeners, and $apply if it needs to update the model. Of course I would like to use the standard ngClick, it just doesn't seem possible at the moment without it throwing an error.
It's probably not the most efficient way to go, but like I said I'm new so go easy on me! I prefixed it 'db' simply because that matches the app I was working on at the time.
Any progress on this? I've been racking my brain trying to get my directive to support the html5 "autofocus" boolean attribute, but angular seems determined not to allow me to do it.
RoyceLithgo - as I understand it, the autofocus attribute in html5 is only relevant on page load and does not effect behaviour after that.
Have you tried the directive I listed above? I used it successfully in a Chrome extension but have not cross browser tested it. I see no reason why it would fail though, unless I've misunderstood what you are trying to achieve.
Actually in the end I did something similar to get the autofocus supported in my directive. I added autofocus to my isolate scope and did this in the linking function:
In my case the element was nested in the directive template, hence the path above. It works, but it does need you to set a value on the autofocus attribute whereas the html5 autofocus attribute doesn't need one. My logic was a lot simpler than yours, mainly because it doesn't support 2-way binding (in my use case, I will always set autofocus to a static "true" value on the first element in the form).
I'm not sure I disagree, or agree. Given that there is a method for managing element validity built into Angular, why would a method for managing element focus in a similar fashion not also be a core feature? It might be nice for use in more primitive directives, like a custom calendar control for example, or maybe a custom color picker. Something were more fine-grained focus control might prove useful.
Activity
pkozlowski-opensource commentedon Jul 18, 2013
Some discussion regarding this in #1250 as well
elgerlambert commentedon Aug 6, 2013
There has been quite some discussion around this topic, so a proper solution requires more effort no doubt, but I thought I'd share the following which has served me well so far.
Sounds like my implementation is similar to that of @ewinslow's, the only real difference being syntax; "focus-model" to me implies it should only watch model properties, whereas I usually have a $scope.state object separate to my $scope.form model.
elgerlambert commentedon Aug 6, 2013
I opted for "focus-when", but I suppose ng-autofocus might fit better with Angular's motto "HTML enhanced"; adding the attribute autofocus to the element when ng-autofocus evaluates to true, similar to how ng-required works..
benlesh commentedon Aug 18, 2013
Since this is a large change set, I've started a discussion on the mailing list here about it: https://groups.google.com/forum/?hl=en#!topic/angular/EQSWV1chf0A
The spirit of the addition, at this point, is that I'm implementing a new controller, similar to an NgModelController, but seperate, as it only worries about managing focus. More details can be found at the link.
I'll have a pull request ready soon.
benlesh commentedon Aug 19, 2013
I have the code ready, but I'm unable to build and run tests.
I want to get this done and submit a pull request for your review, but currently I can't until I get this resolved #3648
kevin-smets commentedon Mar 6, 2014
$timeoutorsetTimeoutworks great indeed, but not so on mobile safari. You have to set the focus inside the event loop of ngClick in order for focus to work properly on iOS (triggering the keyboard), so any timeouts are off limits. I've looked around but found no mention of this problem anywhere, I can't imagine no one else encountered this yet though...The only way to go around this is by using event listeners, and
$applyif it needs to update the model. Of course I would like to use the standard ngClick, it just doesn't seem possible at the moment without it throwing an error.bittenbytailfly commentedon Mar 11, 2014
I'm fairly new to angular, but coming from KnockoutJS, I tried to replicate the 'hasfocus' data binding (see http://knockoutjs.com/documentation/hasfocus-binding.html) which seems to achieve what you want. Here's my effort:
It's probably not the most efficient way to go, but like I said I'm new so go easy on me! I prefixed it 'db' simply because that matches the app I was working on at the time.
RoyceLithgo commentedon Apr 8, 2014
Any progress on this? I've been racking my brain trying to get my directive to support the html5 "autofocus" boolean attribute, but angular seems determined not to allow me to do it.
bittenbytailfly commentedon Apr 8, 2014
RoyceLithgo - as I understand it, the autofocus attribute in html5 is only relevant on page load and does not effect behaviour after that.
Have you tried the directive I listed above? I used it successfully in a Chrome extension but have not cross browser tested it. I see no reason why it would fail though, unless I've misunderstood what you are trying to achieve.
Let me know if it's of any use to you.
RoyceLithgo commentedon Apr 9, 2014
Actually in the end I did something similar to get the autofocus supported in my directive. I added autofocus to my isolate scope and did this in the linking function:
if(scope.autofocus === "true")
{
elm[0].childNodes[1].focus();
}
In my case the element was nested in the directive template, hence the path above. It works, but it does need you to set a value on the autofocus attribute whereas the html5 autofocus attribute doesn't need one. My logic was a lot simpler than yours, mainly because it doesn't support 2-way binding (in my use case, I will always set autofocus to a static "true" value on the first element in the form).
btford commentedon May 21, 2014
I think because the use cases for such a directive might differ, this is a good opportunity for 3rd party modules to implement different solutions.
http://github.com/jgallen23/angular-focus looks like a good start.
I'm going to close this as "not in core," but feel free to post solutions or links to modules here for others to find. Thanks!
benlesh commentedon May 21, 2014
I'm not sure I disagree, or agree. Given that there is a method for managing element validity built into Angular, why would a method for managing element focus in a similar fashion not also be a core feature? It might be nice for use in more primitive directives, like a custom calendar control for example, or maybe a custom color picker. Something were more fine-grained focus control might prove useful.
Honest question. Thanks for your time, @btford.
btford commentedon May 21, 2014
honestly I think the form validation stuff should also be a separate module
benlesh commentedon May 21, 2014
Fair enough. I think I can agree with that.
benlesh commentedon May 21, 2014
Hahaha... my last comment reads funny. I'm sure you were just waiting around to see if I'd agree with you. ;) lol