(EDIT: Ich habe eine aktualisierte Lösung unterhalb dieser Erklärung hinzugefügt)
Mark Rajcok ist der Mann... und seine Antwort ist eine gültige Antwort, aber sie hat hatte einen Fehler (sorry Mark)...
...Versuchen Sie, das Boolean zu verwenden, um den Fokus auf das Eingabefeld zu setzen, dann den Fokus vom Eingabefeld zu entfernen, dann versuchen Sie, es wieder zu fokussieren. Es wird nicht funktionieren, es sei denn, Sie setzen das Boolean wieder auf false zurück, dann $digest, dann setzen Sie es wieder auf true. Selbst wenn Sie einen Zeichenfolgenvergleich in Ihrem Ausdruck verwenden, werden Sie gezwungen sein, die Zeichenfolge zu ändern, $digest, dann sie wieder zurückzusetzen. (Dies wurde mit dem Blur-Ereignis-Handler behoben.)
Also schlage ich diese alternative Lösung vor:
Verwenden Sie ein Ereignis, die vergessene Funktion von Angular.
JavaScript liebt schließlich Ereignisse. Ereignisse sind von Natur aus lose gekoppelt, und noch besser, Sie vermeiden es, einen weiteren $watch zu Ihrem $digest hinzuzufügen.
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on(attr.focusOn, function(e) {
elem[0].focus();
});
};
});
Jetzt könnten Sie es so verwenden:
und dann überall in Ihrer App...
$scope.addNewItem = function () {
/* Hier Dinge einfügen, um ein neues Element hinzuzufügen... */
$scope.$broadcast('newItemAdded');
};
Dies ist großartig, weil Sie mit so etwas alles Mögliche machen können. Zum einen könnten Sie sich in Ereignisse einbinden, die bereits existieren. Zum anderen fangen Sie an, etwas Kluges zu tun, indem Sie verschiedene Teile Ihrer App Ereignisse veröffentlichen lassen, denen andere Teile Ihrer App folgen können.
In jeder Hinsicht schreit diese Art von Sache "ereignisgesteuert" für mich. Ich denke, als Angular-Entwickler geben wir uns wirklich Mühe, $scope-förmige Zapfen in Ereignis-förmige Löcher zu hämmern.
Ist es die beste Lösung? Ich weiß es nicht. Es ist eine Lösung.
Aktualisierte Lösung
Nach dem Kommentar von @ShimonRachlenko unten habe ich meine Methode, dies zu tun, etwas geändert. Jetzt verwende ich eine Kombination aus einem Service und einer Direktive, die ein Ereignis "hinter den Kulissen" behandelt:
Ansonsten ist es das gleiche Prinzip, wie oben beschrieben.
Hier ist ein schnelles Demo-Plunk
Verwendung
app.controller('MyCtrl', function($scope, focus) {
focus('focusMe');
});
Quellcode
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on('focusOn', function(e, name) {
if(name === attr.focusOn) {
elem[0].focus();
}
});
};
});
app.factory('focus', function ($rootScope, $timeout) {
return function(name) {
$timeout(function (){
$rootScope.$broadcast('focusOn', name);
});
}
});