- Wenn ein Modal geöffnet wird, konzentrieren Sie sich auf einen vordefinierten <Eingang> in diesem Modal.
Definieren Sie eine Direktive und lassen Sie sie $ eine Eigenschaft / einen Trigger beobachten, damit sie weiß, wann das Element fokussiert werden muss:
Name: <input type="text" focus-me="shouldBeOpen">
app.directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function (scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function (value) {
console.log('value=', value);
if (value === true) {
$timeout(function () {
element[0].focus();
});
}
});
// to address @blesh's comment, set attribute value to 'false'
// on blur event:
element.bind('blur', function () {
console.log('blur');
scope.$apply(model.assign(scope, false));
});
}
};
}]);
Plunker
Das $ timeout scheint erforderlich zu sein, um dem Modal Zeit zum Rendern zu geben.
'2.' Stellen Sie den Fokus jedes Mal ein, wenn <Eingabe> sichtbar wird (z. B. durch Klicken auf eine Schaltfläche).
Erstellen Sie eine Direktive im Wesentlichen wie oben. Beobachten Sie eine Scope-Eigenschaft und führen Sie sie aus, wenn sie wahr wird (legen Sie sie in Ihrem ng-click-Handler fest) element[0].focus()
. Abhängig von Ihrem Anwendungsfall benötigen Sie möglicherweise ein $ Timeout für diesen:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" ng-model="myInput" focus-me="focusInput"> {{ myInput }}
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.focusMe, function(value) {
if(value === true) {
console.log('value=',value);
//$timeout(function() {
element[0].focus();
scope[attrs.focusMe] = false;
//});
}
});
}
};
});
Plunker
Update 7/2013 : Ich habe gesehen, dass einige Leute meine ursprünglichen Anweisungen zum Isolieren des Gültigkeitsbereichs verwenden und dann Probleme mit eingebetteten Eingabefeldern haben (dh einem Eingabefeld im Modal). Eine Richtlinie ohne neuen Geltungsbereich (oder möglicherweise mit einem neuen Geltungsbereich für Kinder) sollte einen Teil der Schmerzen lindern. Daher habe ich oben die Antwort aktualisiert, um keine isolierten Bereiche zu verwenden. Unten ist die ursprüngliche Antwort:
Ursprüngliche Antwort für 1. unter Verwendung eines isolierten Bereichs:
Name: <input type="text" focus-me="{{shouldBeOpen}}">
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '@focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === "true") {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
Plunker .
Ursprüngliche Antwort für 2. unter Verwendung eines isolierten Bereichs:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" focus-me="focusInput">
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '=focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === true) {
//console.log('trigger',value);
//$timeout(function() {
element[0].focus();
scope.trigger = false;
//});
}
});
}
};
});
Plunker .
Da wir die Eigenschaft trigger / focusInput in der Direktive zurücksetzen müssen, wird '=' für die bidirektionale Datenbindung verwendet. In der ersten Anweisung war '@' ausreichend. Beachten Sie auch, dass wir bei Verwendung von '@' den Triggerwert mit "true" vergleichen, da @ immer zu einer Zeichenfolge führt.
ng-model
im Eingabefeld einen Wert einstelle , geht der Modellwert verloren, wenn ich diese Direktive verwende, wobei der Isolationsbereich verwendet wird. Das Problem tritt nicht auf, wenn ich Joshs Version ohne isolierten Bereich ausprobiere. Immer noch ein Neuling, und ich würde gerne den Unterschied verstehen. Hier ist ein Plunker , der es zeigt.value != "true"
, und das schien mein Problem zu beheben .(BEARBEITEN: Ich habe unter dieser Erklärung eine aktualisierte Lösung hinzugefügt.)
Mark Rajcok ist der Mann ... und seine Antwort ist eine gültige Antwort, aber es
hateinen Defekt gehabt (sorry Mark) ...... Versuchen Sie, den Booleschen Wert zu verwenden, um auf die Eingabe zu fokussieren, verwischen Sie dann die Eingabe und versuchen Sie dann, ihn erneut zu fokussieren. Es wird nur funktionieren, wenn Sie den Booleschen Wert auf false zurücksetzen, dann $ digest und dann wieder auf true zurücksetzen. Selbst wenn Sie in Ihrem Ausdruck einen Zeichenfolgenvergleich verwenden, müssen Sie die Zeichenfolge in etwas anderes ändern, $ Digest, und sie dann wieder ändern.(Dies wurde mit dem Unschärfe-Ereignishandler behoben.)Also schlage ich diese alternative Lösung vor:
Verwenden Sie ein Ereignis, die vergessene Funktion von Angular.
JavaScript liebt Ereignisse schließlich. Ereignisse sind von Natur aus lose miteinander verbunden, und noch besser, Sie vermeiden es, Ihrem $ Digest eine weitere $ watch hinzuzufügen.
Jetzt können Sie es so verwenden:
und dann überall in Ihrer App ...
Das ist großartig, weil man mit so etwas alles Mögliche machen kann. Zum einen könnten Sie an bereits vorhandene Ereignisse anknüpfen. Zum anderen machen Sie etwas Kluges, indem Sie verschiedene Teile Ihrer App Ereignisse veröffentlichen lassen, die andere Teile Ihrer App abonnieren können.
Wie auch immer, diese Art von Dingen schreit "ereignisgesteuert" zu mir. Ich denke, als Angular-Entwickler bemühen wir uns sehr, $ scope-förmige Stifte in ereignisförmige Löcher zu hämmern.
Ist es die beste Lösung? Ich weiß nicht. Es ist eine Lösung.
Aktualisierte Lösung
Nach dem Kommentar von @ ShimonRachlenko unten habe ich meine Methode dazu leicht geändert. Jetzt verwende ich eine Kombination aus einem Dienst und einer Direktive, die ein Ereignis "hinter den Kulissen" behandelt:
Davon abgesehen ist es das gleiche Prinzip wie oben beschrieben.
Hier ist eine kurze Demo Plunk
Verwendungszweck
Quelle
quelle
$broadcast
mit abschließen,$timeout
wenn dies beim Aufrufen des Controllers funktionieren soll. Ansonsten schöne Lösung.Ich habe festgestellt, dass einige der anderen Antworten zu kompliziert sind, wenn alles, was Sie wirklich brauchen, dies ist
Nutzung ist
Wir verwenden das Timeout, um Dinge im Dom rendern zu lassen, obwohl es Null ist, wartet es zumindest darauf - auf diese Weise funktioniert dies in Modalen und so weiter
quelle
ng-click
: Nehmen wir an, das Klicken auf eine Schaltfläche hatng-click="showInput = !showInput
Ihre Eingabe. Fügen Sie dann bei Ihrer tatsächlichen Eingabe hinzung-if="showInput"
. Durch Umschalten der Schaltfläche wird die Anweisung jedes Mal erneut ausgeführt. Ich hatte ein Problem damit, als ich es benutzte,ng-show
was der falsche Ansatz ist.HTML hat ein Attribut
autofocus
.http://www.w3schools.com/tags/att_input_autofocus.asp
quelle
Sie können auch die in eckig integrierte jqlite-Funktionalität verwenden.
angular.element('.selector').trigger('focus');
quelle
Looking up elements via selectors is not supported by jqLite!
Dies funktioniert gut und bietet eine eckige Möglichkeit, die Eingabesteuerung zu fokussieren
Dies ist zwar keine reine Winkelmethode für die Ausführung der Aufgabe, die Syntax folgt jedoch dem Winkelstil. Jquery spielt indirekt eine Rolle und greift über Angular (jQLite => JQuery Light) direkt auf DOM zu.
Bei Bedarf kann dieser Code einfach in eine einfache Winkelanweisung eingefügt werden, auf die direkt zugegriffen werden kann.
quelle
Looking up elements via selectors is not supported by jqLite!
angular.element
wird es zu einem Wrapper für$() / jQuery()
. Ohne das wird das nicht funktionieren und Sie verwenden im Grunde sowieso nur jQuery (aber korrigieren Sie mich, wenn ich falschIch denke nicht, dass $ timeout eine gute Möglichkeit ist, das Element auf die Erstellung zu konzentrieren. Hier ist eine Methode mit integrierter Winkelfunktionalität, die aus den trüben Tiefen der Winkeldokumente ausgegraben wurde. Beachten Sie, wie das Attribut "Link" für Pre-Link- und Post-Link-Funktionen in "Pre" und "Post" unterteilt werden kann.
Arbeitsbeispiel: http://plnkr.co/edit/Fj59GB
Vollständige Dokumente der AngularJS-Richtlinie: https://docs.angularjs.org/api/ng/service/$compile
quelle
Hier ist meine ursprüngliche Lösung:
Plunker
Und der HTML:
Was es macht:
Es fokussiert die Eingabe, wenn sie mit ng-show sichtbar wird. Keine Verwendung von $ watch oder $ on hier.
quelle
Ich habe eine Zwei-Wege-Bindungsfokus-Direktive geschrieben, genau wie das Modell kürzlich.
Sie können die Fokusanweisung wie folgt verwenden:
Wenn Sie eine Bereichsvariable von FocusVariable festlegen
true
an einer beliebigen Stelle in Ihrem Controller , wird die Eingabe fokussiert. Und wenn Sie Ihre Eingabe "verwischen" möchten, kann someFocusVariable auf false gesetzt werden. Es ist wie Mark Rajcoks erste Antwort, aber mit Zwei-Wege-Bindung.Hier ist die Richtlinie:
Verwendungszweck:
Hier ist die Geige:
http://fiddle.jshell.net/ubenzer/9FSL4/8/
quelle
Für diejenigen, die Angular mit dem Bootstrap-Plugin verwenden:
http://angular-ui.github.io/bootstrap/#/modal
Sie können sich an das
opened
Versprechen der modalen Instanz halten:quelle
$timeout
mit50ms
in Not statt0
.Ich fand es nützlich, einen allgemeinen Ausdruck zu verwenden. Auf diese Weise können Sie beispielsweise den Fokus automatisch verschieben, wenn der eingegebene Text gültig ist
Oder fokussieren Sie automatisch, wenn der Benutzer ein Feld mit fester Länge ausfüllt
Und natürlich nach dem Laden fokussieren
Der Code für die Richtlinie:
quelle
Einen Zombie nicht wiederzubeleben oder meine eigene Anweisung zu stecken (ok, genau das mache ich):
https://github.com/hiebj/ng-focus-if
http://plnkr.co/edit/MJS3zRk079Mu72o5A9l6?p=preview
quelle
Ein offizieller Weg, sich zu konzentrieren, ist zunächst die Roadmap für 1.1 . In der Zwischenzeit können Sie eine Anweisung schreiben, um den Einstellungsfokus zu implementieren.
Zweitens ist eine Problemumgehung erforderlich, um den Fokus auf ein Element zu legen, nachdem es sichtbar geworden ist. Verzögern Sie einfach Ihren Aufruf von element focus () mit a
$timeout
.Da das gleiche Controller-Modify-DOM-Problem für Fokus, Unschärfe und Auswahl besteht, schlage ich eine
ng-target
Direktive vor:Angular Thread hier: http://goo.gl/ipsx4 , und weitere Details hier gebloggt: http://goo.gl/4rdZa
Die folgende Anweisung erstellt eine
.focus()
Funktion in Ihrem Controller, die durch Ihrng-target
Attribut angegeben wird. (Es erstellt ein.blur()
und ein.select()
auch.) Demo: http://jsfiddle.net/bseib/WUcQX/quelle
ngFocus
scheint eine Möglichkeit zu sein,focus
Ereignisse zu behandeln , nicht eine Möglichkeit, den Fokus auf ein Element zu legen .Anstatt eine eigene Direktive zu erstellen, können Sie einfach Javascript-Funktionen verwenden, um einen Fokus zu erzielen.
Hier ist ein Beispiel.
In der HTML-Datei:
In einer Datei Javascript, beispielsweise in einem Controller, in dem Sie den Fokus aktivieren möchten:
quelle
Wenn Sie nur einen einfachen Fokus wünschen, der durch einen Klick gesteuert wird.
Html:
Richtlinie:
quelle
Eine einfache, die gut mit Modalitäten funktioniert:
Beispiel
quelle
Sie können einfach eine Direktive erstellen, die den Fokus auf das dekorierte Element in postLinking erzwingt:
Dann in Ihrem HTML:
Dies würde für Modals und ng-if-umgeschaltete Elemente funktionieren, nicht für ng-show, da postLinking nur bei der HTML-Verarbeitung erfolgt.
quelle
Mark und Blesh haben großartige Antworten. Marks hat jedoch einen Fehler, auf den Blesh hinweist (abgesehen davon, dass er komplex zu implementieren ist), und ich bin der Meinung, dass Bleshs Antwort einen semantischen Fehler bei der Erstellung eines Dienstes aufweist, bei dem es speziell darum geht, eine Fokusanforderung an das Frontend zu senden, wenn wirklich nur ein Weg erforderlich war verzögern Sie das Ereignis, bis alle Anweisungen abgehört haben.
Hier ist also, was ich letztendlich getan habe, was viel von Bleshs Antwort stiehlt, aber die Semantik des Controller-Ereignisses und des "After-Load" -Dienstes getrennt hält.
Dies ermöglicht es dem Controller-Ereignis, einfach für andere Dinge als nur das Fokussieren eines bestimmten Elements eingebunden zu werden, und ermöglicht es auch, den Overhead der "Nachlade" -Funktionalität nur dann zu verursachen, wenn es benötigt wird, was in vielen Fällen möglicherweise nicht der Fall ist.
Verwendungszweck
Quelle
quelle
Dies ist auch möglich zu verwenden
ngModelController
. Arbeiten mit 1.6+ (weiß nicht mit älteren Versionen).HTML
JS
- -
NB: Abhängig vom Kontext müssen Sie möglicherweise eine Timeout-Funktion einbinden.
NB²: Bei der Verwendung
controllerAs
ist dies fast das gleiche. Ersetzen Sie einfachname="myForm"
mitname="vm.myForm"
und in JS,vm.myForm.myText.$$element.focus();
.quelle
Wahrscheinlich die einfachste Lösung für das ES6-Alter.
Durch Hinzufügen der folgenden Liner-Direktive wird das HTML-Attribut "Autofokus" für Angular.js wirksam.
Jetzt können Sie einfach die HTML5-Autofokus-Syntax wie folgt verwenden:
quelle
.directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
Nur ein Neuling hier, aber ich war in der Lage, es in einem ui.bootstrap.modal mit dieser Direktive zum Laufen zu bringen :
und in der $ modal.open-Methode habe ich das Folgende verwendet, um das Element anzugeben, auf das der Fokus gesetzt werden soll:
Auf der Vorlage habe ich folgendes:
quelle
Die folgende Anweisung hat den Trick für mich getan. Verwenden Sie für die Eingabe dasselbe Autofokus-HTML-Attribut.
quelle
Wenn Sie modalInstance verwenden und über das Objekt verfügen, können Sie "then" verwenden, um nach dem Öffnen des Modals Aktionen auszuführen. Wenn Sie modalInstance nicht verwenden und fest codiert sind, um das Modal zu öffnen, können Sie das Ereignis verwenden. Das $ timeout ist keine gute Lösung.
Sie können Folgendes tun (Bootstrap3):
Bei modalInstance können Sie in der Bibliothek nachsehen, wie der Code nach dem Öffnen von modal ausgeführt wird.
Verwenden Sie $ timeout nicht so, das $ timeout kann 0, 1, 10, 30, 50, 200 oder mehr sein. Dies hängt vom Client-Computer und dem Vorgang zum Öffnen von Modal ab.
Verwenden Sie nicht $ timeout. Lassen Sie sich von der Methode mitteilen, wann Sie sich konzentrieren können.
Ich hoffe das hilft! :) :)
quelle
Die gesamte vorherige Antwort funktioniert nicht, wenn das gewünschte Fokuselement in eine Direktivenvorlage eingefügt wird. Die folgende Direktive passt sowohl zu einfachen Elementen als auch zu injizierten Direktiven (ich habe sie in Typoskript geschrieben ). es akzeptiert Selektor für inneres fokussierbares Element. Wenn Sie nur das Selbstelement fokussieren müssen, senden Sie keinen Selektorparameter an die Direktive:
}}
Anwendungsbeispiel für einfaches Element:
Anwendungsbeispiel für inneres Element (normalerweise für dynamisch injiziertes Element wie Direktive mit Vorlage):
Sie können einen beliebigen jQuery-Selektor anstelle von "Eingabe" verwenden.
quelle
Ich bearbeite die focusMe-Direktive von Mark Rajcok, um für mehrere Fokusse in einem Element zu arbeiten.
HTML:
in AngularJs Controller:
AngulaJS-Richtlinie:
quelle
Ich möchte zu dieser Diskussion beitragen, nachdem ich nach einer besseren Lösung gesucht und sie nicht gefunden habe, sondern sie stattdessen erstellen muss.
Kriterien: 1. Die Lösung sollte unabhängig vom Umfang des übergeordneten Controllers sein, um die Wiederverwendbarkeit zu verbessern. 2. Vermeiden Sie die Verwendung von $ watch, um einen bestimmten Zustand zu überwachen. Dies ist langsam, vergrößert die Digest-Schleife und erschwert das Testen. 3. Vermeiden Sie $ timeout oder $ scope. $ Apply (), um eine Digest-Schleife auszulösen. 4. In dem Element, in dem die Richtlinie verwendet wird, befindet sich ein Eingabeelement.
Dies ist die Lösung, die mir am besten gefallen hat:
Richtlinie:
Html:
Ich hoffe das hilft jemandem da draußen!
quelle
Es ist einfach ... versuchen Sie es
html
Javascript
quelle
Wenn Sie den Fokus auf ein bestimmtes Element legen möchten, können Sie den folgenden Ansatz verwenden.
Erstellen Sie einen Dienst namens
focus
.Injizieren Sie es in den Controller, von dem aus Sie anrufen möchten.
Rufen Sie diesen Service an.
quelle
Ich halte die Richtlinie für unnötig. Verwenden Sie HTML-ID- und Klassenattribute, um das erforderliche Element auszuwählen, und lassen Sie den Dienst document.getElementById oder document.querySelector verwenden, um den Fokus (oder jQuery-Äquivalente) anzuwenden.
Markup ist eine Standard-HTML- / Winkelanweisung mit hinzugefügten IDs / Klassen zur Auswahl
Controller sendet Ereignis
Im UI-Dienst wird querySelector verwendet. Wenn mehrere Übereinstimmungen vorliegen (z. B. aufgrund der Klasse), wird nur die erste zurückgegeben
Möglicherweise möchten Sie $ timeout () verwenden, um einen Digest-Zyklus zu erzwingen
quelle
Wirf einfach einen Kaffee hinein.
quelle