Was ist der "winkelige Weg", um den Fokus auf das Eingabefeld in AngularJS zu setzen?
Spezifischere Anforderungen:
<input>
in diesem Modal.<input>
sichtbar wird (z. B. durch Klicken auf eine Schaltfläche), setzen Sie den Fokus darauf.Ich habe versucht, die erste Anforderung zu erfüllen mit autofocus
, dies funktioniert jedoch nur, wenn das Modal zum ersten Mal geöffnet wird, und nur in bestimmten Browsern (z. B. in Firefox funktioniert es nicht).
Jede Hilfe wird geschätzt.
- Wenn ein Modal geöffnet ist, stellen Sie den Fokus auf eine vordefinierte <Eingabe> in diesem Modal.
Definieren Sie eine Direktive und lassen Sie sie $ eine Eigenschaft/einen Trigger überwachen, damit sie weiß, wann das Element fokussiert werden soll:
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));
});
}
};
}]);
Das $ timeout scheint erforderlich zu sein, um dem Modal Zeit zum Rendern zu geben.
'2.' Jedes Mal, wenn <Eingabe> sichtbar wird (z. B. durch Klicken auf eine Schaltfläche), setzen Sie den Fokus darauf.
Erstellen Sie im Wesentlichen eine Direktive wie oben. Achten Sie auf eine Bereichseigenschaft, und wenn sie wahr wird (setzen Sie sie in Ihrem Ng-Click-Handler), führen Sie element[0].focus()
aus. Abhängig von Ihrem Anwendungsfall benötigen Sie möglicherweise kein $ timeout für diesen Anwendungsfall:
<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;
//});
}
});
}
};
});
Update 7/2013: Ich habe gesehen, dass ein paar Leute meine ursprünglichen Isolate-Bereichsanweisungen verwendet haben und dann Probleme mit eingebetteten Eingabefeldern (d. H. Einem Eingabefeld im Modal) haben. Eine Richtlinie ohne neuen Geltungsbereich (oder möglicherweise einen neuen Geltungsbereich für Kinder) sollte einige der Schmerzen lindern. Also habe ich die Antwort so aktualisiert, dass keine isolierten Bereiche verwendet werden. 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 trigger/focusInput -Eigenschaft in der Direktive zurücksetzen müssen, wird '=' für die bidirektionale Datenbindung verwendet. In der ersten Direktive war "@" ausreichend. Beachten Sie auch, dass bei Verwendung von '@' der Auslöserwert mit "true" verglichen wird, da @ immer eine Zeichenfolge ergibt.
Mark Rajcok ist der Mann ... und seine Antwort ist eine gültige Antwort, aber es ist hat hatte einen Defekt (sorry Mark) ...
... Versuchen Sie, die Eingabe mit dem boolean zu fokussieren, die Unschärfe zu verwischen und dann die Eingabe erneut zu fokussieren. Es funktioniert nicht, es sei denn, Sie setzen den Booleschen Wert auf false zurück, dann $ digest und setzen ihn dann wieder auf true zurück. Selbst wenn Sie in Ihrem Ausdruck einen Zeichenfolgenvergleich verwenden, müssen Sie die Zeichenfolge in etwas anderes ändern ($ digest) und dann wieder zurücksetzen. (Dies wurde mit dem Blur-Event-Handler angesprochen.)
Ich schlage also diese alternative Lösung vor:
JavaScript liebt Events doch. Ereignisse sind von Natur aus lose miteinander verbunden, und noch besser vermeiden Sie es, eine weitere $ 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önntest du es so benutzen:
<input type="text" focus-on="newItemAdded" />
und dann überall in Ihrer App ...
$scope.addNewItem = function () {
/* stuff here to add a new item... */
$scope.$broadcast('newItemAdded');
};
Das ist großartig, weil man mit so etwas alle möglichen Dinge tun kann. Zum einen könnten Sie an bereits bestehende Ereignisse knüpfen. Zum anderen beginnen Sie etwas Kluges zu tun, 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 wirklich sehr darum, ope-förmige Stifte in Event-Form-Löcher zu schlagen.
Ist es die beste Lösung? Ich weiß nicht. Es ist a Lösung.
Nach dem Kommentar von @ ShimonRachlenko habe ich meine Methode etwas geändert. Jetzt verwende ich eine Kombination aus einem Dienst und einer Direktive, die ein Ereignis "hinter den Kulissen" abwickelt:
Abgesehen davon ist es das gleiche Prinzip, das oben beschrieben wurde.
Hier ist eine kurze Demo Plunk
<input type="text" focus-on="focusMe"/>
app.controller('MyCtrl', function($scope, focus) {
focus('focusMe');
});
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);
});
}
});
Ich habe festgestellt, dass einige der anderen Antworten zu kompliziert sind, wenn Sie dies wirklich nur brauchen
app.directive('autoFocus', function($timeout) {
return {
restrict: 'AC',
link: function(_scope, _element) {
$timeout(function(){
_element[0].focus();
}, 0);
}
};
});
nutzung ist
<input name="theInput" auto-focus>
Wir verwenden das Timeout, um Dinge im Dom rendern zu lassen, auch wenn es null ist. Es wird zumindest darauf gewartet - so funktioniert das in Modalen und so weiter
HTML hat ein Attribut autofocus
.
<input type="text" name="fname" autofocus>
Sie können auch die in angle integrierte jqlite-Funktionalität verwenden.
angular.element('.selector').trigger('focus');
Dies funktioniert gut und eine winkelige Möglichkeit, die Eingabesteuerung zu fokussieren
angular.element('#elementId').focus()
Dies ist zwar keine reine Winkelmethode, aber die Syntax folgt dem Winkelstil. Jquery spielt indirekt eine Rolle und greift direkt auf DOM mit Angular zu (jQLite => JQuery Light).
Bei Bedarf kann dieser Code problemlos in eine einfache Winkelanweisung eingefügt werden, in der das Element direkt verfügbar ist.
Ich glaube nicht, dass $ timeout eine gute Möglichkeit ist, das Element auf die Erstellung zu fokussieren. Hier ist eine Methode, die die integrierte Winkelfunktionalität verwendet, die aus den trüben Tiefen der Winkeldokumente ausgegraben wurde. Beachten Sie, wie das Attribut "link" für Funktionen vor dem Link und nach dem Link in "pre" und "post" unterteilt werden kann.
Arbeitsbeispiel: http://plnkr.co/edit/Fj59DE
// this is the directive you add to any element you want to highlight after creation
Guest.directive('autoFocus', function() {
return {
link: {
pre: function preLink(scope, element, attr) {
console.debug('prelink called');
// this fails since the element hasn't rendered
//element[0].focus();
},
post: function postLink(scope, element, attr) {
console.debug('postlink called');
// this succeeds since the element has been rendered
element[0].focus();
}
}
}
});
<input value="hello" />
<!-- this input automatically gets focus on creation -->
<input value="world" auto-focus />
Ausführliche AngularJS-Richtlinien: https://docs.angularjs.org/api/ng/service/$compile
Hier ist meine ursprüngliche Lösung:
var app = angular.module('plunker', []);
app.directive('autoFocus', function($timeout) {
return {
link: function (scope, element, attrs) {
attrs.$observe("autoFocus", function(newValue){
if (newValue === "true")
$timeout(function(){element[0].focus()});
});
}
};
});
Und das HTML:
<button ng-click="isVisible = !isVisible">Toggle input</button>
<input ng-show="isVisible" auto-focus="{{ isVisible }}" value="auto-focus on" />
Es fokussiert die Eingabe, sobald sie mit ng-show sichtbar wird. Keine Verwendung von $ watch oder $ on hier.
Ich habe eine bidirektionale verbindliche Direktive geschrieben, genau wie das Modell kürzlich.
Sie können die Fokusanweisung folgendermaßen verwenden:
<input focus="someFocusVariable">
Wenn Sie an einem beliebigen Ort in Ihrem Controller die VARIABLE-Variable "Variable" true
definieren, wird die Eingabe fokussiert. Wenn Sie Ihre Eingabe "verwischen" möchten, kann someFocusVariable auf "false" gesetzt werden. Es ist wie die erste Antwort von Mark Rajcok, jedoch mit wechselseitiger Bindung.
Hier ist die Direktive:
function Ctrl($scope) {
$scope.model = "ahaha"
$scope.someFocusVariable = true; // If you want to focus initially, set this to true. Else you don't need to define this at all.
}
angular.module('experiement', [])
.directive('focus', function($timeout, $parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.focus, function(newValue, oldValue) {
if (newValue) { element[0].focus(); }
});
element.bind("blur", function(e) {
$timeout(function() {
scope.$apply(attrs.focus + "=false");
}, 0);
});
element.bind("focus", function(e) {
$timeout(function() {
scope.$apply(attrs.focus + "=true");
}, 0);
})
}
}
});
Verwendungszweck:
<div ng-app="experiement">
<div ng-controller="Ctrl">
An Input: <input ng-model="model" focus="someFocusVariable">
<hr>
<div ng-click="someFocusVariable=true">Focus!</div>
<pre>someFocusVariable: {{ someFocusVariable }}</pre>
<pre>content: {{ model }}</pre>
</div>
</div>
Hier ist die Geige:
Für diejenigen, die Angular mit dem Bootstrap-Plugin verwenden:
http://angular-ui.github.io/bootstrap/#/modal
Sie können sich in das Versprechen opened
der modalen Instanz einhaken:
modalInstance.opened.then(function() {
$timeout(function() {
angular.element('#title_input').trigger('focus');
});
});
modalInstance.result.then(function ( etc...
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
<button type="button" moo-focus-expression="form.phone.$valid">
Oder fokussieren Sie automatisch, wenn der Benutzer ein Feld mit fester Länge ausfüllt
<button type="submit" moo-focus-expression="smsconfirm.length == 6">
Und natürlich Fokus nach dem Laden
<input type="text" moo-focus-expression="true">
Der Code für die Direktive:
.directive('mooFocusExpression', function ($timeout) {
return {
restrict: 'A',
link: {
post: function postLink(scope, element, attrs) {
scope.$watch(attrs.mooFocusExpression, function (value) {
if (attrs.mooFocusExpression) {
if (scope.$eval(attrs.mooFocusExpression)) {
$timeout(function () {
element[0].focus();
}, 100); //need some delay to work with ng-disabled
}
}
});
}
}
};
});
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:
<input type="text" id="myInputId" />
In einem Datei-Javascript, beispielsweise in einem Controller, in dem Sie den Fokus aktivieren möchten:
document.getElementById("myInputId").focus();
Einen Zombie nicht wiederbeleben oder meine eigene Anweisung anbringen (ok, genau das mache ich):
https://github.com/hiebj/ng-focus-if
http://plnkr.co/edit/MJS3zRk079Mu72o5A9l6?p=preview
<input focus-if />
(function() {
'use strict';
angular
.module('focus-if', [])
.directive('focusIf', focusIf);
function focusIf($timeout) {
function link($scope, $element, $attrs) {
var dom = $element[0];
if ($attrs.focusIf) {
$scope.$watch($attrs.focusIf, focus);
} else {
focus(true);
}
function focus(condition) {
if (condition) {
$timeout(function() {
dom.focus();
}, $scope.$eval($attrs.focusDelay) || 0);
}
}
}
return {
restrict: 'A',
link: link
};
}
})();
Erstens ist ein offizieller Weg, den Fokus auf die Roadmap für 1.1 zu legen. Inzwischen können Sie eine Direktive schreiben, um den Einstellungsfokus zu implementieren.
Zweitens erfordert das Festlegen eines Fokus auf ein Element, nachdem es sichtbar wurde, eine Umgehung. Verzögern Sie einfach Ihren Aufruf von element focus () mit einem $timeout
.
Da das gleiche Controller-Änderungs-DOM-Problem für Fokus, Unschärfe und Auswahl besteht, schlage ich vor, eine ng-target
-Direktive zu haben:
<input type="text" x-ng-model="form.color" x-ng-target="form.colorTarget">
<button class="btn" x-ng-click="form.colorTarget.focus()">do focus</button>
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, wie durch Ihr ng-target
-Attribut angegeben. (Außerdem werden eine .blur()
und eine .select()
erstellt.) Demo: http://jsfiddle.net/bseib/WUcQX/
Eine einfache, die gut mit Modalen funktioniert:
.directive('focusMeNow', ['$timeout', function ($timeout)
{
return {
restrict: 'A',
link: function (scope, element, attrs)
{
$timeout(function ()
{
element[0].focus();
});
}
};
}])
Beispiel
<input ng-model="your.value" focus-me-now />
Wenn Sie nur einen einfachen Fokus wünschen, der durch einen Klick mit der Maus gesteuert wird.
Html:
<input ut-focus="focusTigger">
<button ng-click="focusTrigger=!focusTrigger" ng-init="focusTrigger=false"></button>
Richtlinie:
'use strict'
angular.module('focus',['ng'])
.directive('utFocus',function($timeout){
return {
link:function(scope,elem,attr){
var focusTarget = attr['utFocus'];
scope.$watch(focusTarget,function(value){
$timeout(function(){
elem[0].focus();
});
});
}
}
});
Mark und Blesh haben großartige Antworten. Allerdings hat Mark einen Fehler, auf den Blesh hinweist (abgesehen davon, dass er komplex zu implementieren ist), und ich glaube, dass die Antwort von Blesh einen semantischen Fehler enthält, wenn ein Dienst erstellt wird, der speziell dazu dient, eine Fokusanforderung an das Frontend zu senden, wenn wirklich nur ein Weg dorthin war verzögern Sie das Ereignis, bis alle Anweisungen zugehört haben.
Hier ist das, was ich am Ende getan habe, was sehr viel von Bleshs Antwort stiehlt, die Semantik des Controller-Ereignisses und des "after load" -Services jedoch getrennt hält.
Dadurch kann das Controller-Ereignis einfach für andere Dinge als das Fokussieren auf ein bestimmtes Element festgelegt werden, und es ist auch möglich, den Overhead der "After-Load" -Funktionalität nur dann zu tragen, wenn dies erforderlich ist, was in vielen Fällen nicht unbedingt der Fall ist.
<input type="text" focus-on="controllerEvent"/>
app.controller('MyCtrl', function($scope, afterLoad) {
function notifyControllerEvent() {
$scope.$broadcast('controllerEvent');
}
afterLoad(notifyControllerEvent);
});
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on(attr.focusOn, function(e, name) {
elem[0].focus();
});
};
});
app.factory('afterLoad', function ($rootScope, $timeout) {
return function(func) {
$timeout(func);
}
});
Dies ist auch möglich, um ngModelController
zu verwenden. Arbeiten mit 1.6+ (weiß nicht mit älteren Versionen).
HTML
<form name="myForm">
<input type="text" name="myText" ng-model="myText">
</form>
JS
$scope.myForm.myText.$$element.focus();
-
NB .: Je nach Kontext müssen Sie möglicherweise eine Timeout-Funktion verwenden.
Anmerkung: Bei Verwendung von controllerAs
ist dies nahezu gleich. Ersetzen Sie einfach name="myForm"
durch name="vm.myForm"
und in JS vm.myForm.myText.$$element.focus();
.
Sie können einfach eine Direktive erstellen, die das postLinking auf das dekorierte Element konzentriert:
angular.module('directives')
.directive('autoFocus', function() {
return {
restrict: 'AC',
link: function(_scope, _element) {
_element[0].focus();
}
};
});
Dann in deiner HTML:
<input type="text" name="first" auto-focus/> <!-- this will get the focus -->
<input type="text" name="second"/>
Dies würde für Modals und ng-if-Elemente funktionieren, nicht für ng-show, da PostLinking nur bei der HTML-Verarbeitung erfolgt.
Wahrscheinlich die einfachste Lösung im ES6-Zeitalter.
Durch das Hinzufügen einer Liner-Direktive wird das HTML-Autofokusattribut für Angular.js wirksam.
.directive('autofocus', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())}))
Jetzt können Sie die HTML5-Autofokus-Syntax wie folgt verwenden:
<input type="text" autofocus>
Die folgende Anweisung hat den Trick für mich gemacht. Verwenden Sie das gleiche Autofokus-HTML-Attribut für die Eingabe.
.directive('autofocus', [function () {
return {
require : 'ngModel',
restrict: 'A',
link: function (scope, element, attrs) {
element.focus();
}
};
}])
Nur ein Neuling hier, aber ich konnte es in einer ui.bootstrap.modal mit dieser Direktive funktionieren lassen:
directives.directive('focus', function($timeout) {
return {
link : function(scope, element) {
scope.$watch('idToFocus', function(value) {
if (value === element[0].id) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
und in der $ modal.open-Methode habe ich folgendes verwendet, um das Element anzugeben, an dem der Fokus gesetzt werden soll:
var d = $modal.open({
controller : function($scope, $modalInstance) {
...
$scope.idToFocus = "cancelaAteste";
}
...
});
auf der Vorlage habe ich folgendes:
<input id="myInputId" focus />
Wenn Sie modalInstance verwenden und über das Objekt verfügen, können Sie mit "dann" Aktionen ausführen, nachdem Sie das Modal geöffnet haben. Wenn Sie nicht die modalInstance verwenden und zum Öffnen des Modals hartcodiert sind, können Sie das Ereignis verwenden. Das $ Timeout ist keine gute Lösung.
Sie können (Bootstrap3) tun:
$("#" + modalId).on("shown.bs.modal", function() {
angular.element("[name='name']").focus();
});
Bei modalInstance können Sie in der Bibliothek nachsehen, wie der Code nach dem Öffnen von modal ausgeführt wird.
Verwenden Sie kein $ timeout wie dieses. Das $ timeout kann 0, 1, 10, 30, 50, 200 oder mehr sein. Dies hängt vom Clientcomputer und dem Vorgang zum Öffnen von Modal ab.
$ Timeout nicht verwenden, lassen Sie sich durch die Methode mitteilen, wann Sie fokussieren können;)
Ich hoffe das hilft! :)
Ich bearbeite die Direktive focusMe von Mark Rajcok, um in einem Element mehrere Fokusbereiche zu definieren.
HTML:
<input focus-me="myInputFocus" type="text">
in AngularJs Controller:
$scope.myInputFocus= true;
AngulaJS-Richtlinie:
app.directive('focusMe', function ($timeout, $parse) {
return {
link: function (scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function (value) {
if (value === true) {
$timeout(function () {
scope.$apply(model.assign(scope, false));
element[0].focus();
}, 30);
}
});
}
};
});
Die gesamte vorhergehende Antwort funktioniert nicht, wenn das gewünschte Fokuselement in eine Direktive-Vorlage eingefügt wird .. Die folgende Direktive passt sowohl zu einem einfachen Element als auch zu einem injizierten Direktive-Element (ich habe es in TypeScript geschrieben). Es akzeptiert den Wähler für das innere fokussierbare Element. Wenn Sie nur das self-Element fokussieren müssen - senden Sie keinen Auswahlparameter an die Direktive:
module APP.Directives {
export class FocusOnLoadDirective implements ng.IDirective {
priority = 0;
restrict = 'A';
constructor(private $interval:any, private $timeout:any) {
}
link = (scope:ng.IScope, element:JQuery, attrs:any) => {
var _self = this;
var intervalId:number = 0;
var clearInterval = function () {
if (intervalId != 0) {
_self.$interval.cancel(intervalId);
intervalId = 0;
}
};
_self.$timeout(function(){
intervalId = _self.$interval(function () {
let focusableElement = null;
if (attrs.focusOnLoad != '') {
focusableElement = element.find(attrs.focusOnLoad);
}
else {
focusableElement = element;
}
console.debug('focusOnLoad directive: trying to focus');
focusableElement.focus();
if (document.activeElement === focusableElement[0]) {
clearInterval();
}
}, 100);
scope.$on('$destroy', function () {
// Make sure that the interval is destroyed too
clearInterval();
});
});
};
public static factory = ():ng.IDirectiveFactory => {
let directive = ($interval:any, $timeout:any) => new FocusOnLoadDirective($interval, $timeout);
directive.$inject = ['$interval', '$timeout'];
return directive;
};
}
angular.module('common').directive('focusOnLoad', FocusOnLoadDirective.factory());
}
anwendungsbeispiel für einfaches Element:
<button tabindex="0" focus-on-load />
anwendungsbeispiel für inneres Element (normalerweise für dynamisch injiziertes Element wie Direktive mit Vorlage):
<my-directive focus-on-load="input" />
sie können einen beliebigen jQuery-Selektor anstelle von "input" verwenden.
Wenn Sie den Fokus auf ein bestimmtes Element setzen möchten, können Sie den folgenden Ansatz verwenden.
Erstellen Sie einen Dienst mit dem Namen focus
.
angular.module('application')
.factory('focus', function ($timeout, $window) {
return function (id) {
$timeout(function () {
var element = $window.document.getElementById(id);
if (element)
element.focus();
});
};
});
Injizieren Sie es in den Controller, von dem aus Sie anrufen möchten.
Rufen Sie diesen Dienst an.
Ich möchte zu dieser Diskussion beitragen, nachdem ich nach einer besseren Lösung gesucht habe und sie nicht gefunden habe, sondern erst schaffen 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 bestimmte Zustände zu überwachen. Dies ist sowohl langsam, erhöht die Digest-Schleife und erschwert das Testen. Vermeiden Sie $ timeout oder $ scope. $ Apply (), um eine Digest-Schleife auszulösen . 4. Ein Eingabeelement ist in dem Element vorhanden, in dem die Richtlinie offen verwendet wird.
Diese Lösung hat mir am besten gefallen:
Richtlinie:
.directive('focusInput', [ function () {
return {
scope: {},
restrict: 'A',
compile: function(elem, attr) {
elem.bind('click', function() {
elem.find('input').focus();
});
}
};
}]);
Html:
<div focus-input>
<input/>
</div>
Ich hoffe, das hilft jemandem da draußen!
Es ist einfach ... probiere es aus
html
<select id="ddl00">
<option>"test 01"</option>
</select>
Javascript
document.getElementById("ddl00").focus();
sie können die folgende Direktive verwenden, die einen Bool-Wert in der HTML-Eingabe liefert, um sich darauf zu konzentrieren ...
//js file
angular.module("appName").directive("ngFocus", function () {
return function (scope, elem, attrs, ctrl) {
if (attrs.ngFocus === "true") {
$(elem).focus();
}
if (!ctrl) {
return;
}
elem.on("focus", function () {
elem.addClass("has-focus");
scope.$apply(function () {
ctrl.hasFocus = true;
});
});
};
});
<!-- html file -->
<input type="text" ng-focus="boolValue" />
Sie können sogar eine Funktion in Ihrem Controller auf den ngFocus-Direktionswert setzen Beachten Sie den folgenden Code ...
<!-- html file -->
<input type="text" ng-focus="myFunc()" />
//controller file
$scope.myFunc=function(){
if(condition){
return true;
}else{
return false;
}
}
diese Anweisung wird ausgeführt, wenn die HTML-Seite gerendert wird.
Ich denke, die Richtlinie ist unnötig. Verwenden Sie die HTML-ID und Klassenattribute, um das erforderliche Element auszuwählen. Der Dienst kann document.getElementById oder document.querySelector verwenden, um den Fokus (oder jQuery-Entsprechungen) anzuwenden.
Markup ist eine Standard-HTML-/Winkel-Direktive mit hinzugefügten ID/Klassen zur Auswahl
<input id="myInput" type="text" ng-model="myInputModel" />
Controller sendet Ereignis
$scope.$emit('ui:focus', '#myInput');
Im UI-Dienst wird querySelector verwendet. Wenn es mehrere Übereinstimmungen gibt (z. B. aufgrund der Klasse), wird nur der erste zurückgegeben
$rootScope.$on('ui:focus', function($event, selector){
var elem = document.querySelector(selector);
if (elem) {
elem.focus();
}
});
Möglicherweise möchten Sie $ timeout () verwenden, um einen Digest-Zyklus zu erzwingen
Sie sind sich nicht sicher, ob die Verwendung des Timeouts eine gute Idee ist. Dies funktioniert jedoch für ng-repeat, da dieser Code ausgeführt wird, NACHDUTALJS aktualisiert das DOM. Sie stellen also sicher, dass alle Objekte vorhanden sind:
myApp.directive('onLastRepeat', [function () {
return function (scope, element, attrs) {
if (scope.$last) setTimeout(function () {
scope.$emit('onRepeatLast', element, attrs);
}, 1);
};
}]);
//controller for grid
myApp.controller('SimpleController', ['$scope', '$timeout', '$http', function ($scope, $timeout, $http)
{
var newItemRemoved = false;
var requiredAlert = false;
//this event fires up when angular updates the dom for the last item
//it's observed, so here, we stop the progress bar
$scope.$on('onRepeatLast', function (scope, element, attrs) {
//$scope.complete();
console.log('done done!');
$("#txtFirstName").focus();
});
}]);
Programmgesteuert eine beliebige Aktion für ein Element aufrufen: click (), focus (), select () ...
Verwendungszweck:
<a href="google.com" auto-action="{'click': $scope.autoclick, 'focus': $scope.autofocus}">Link</a>
Richtlinie:
/**
* Programatically Triggers given function on the element
* Syntax: the same as for ng-class="object"
* Example: <a href="google.com" auto-action="{'click': autoclick_boolean, 'focus': autofocus_boolean}">Link</a>
*/
app.directive('focusMe', function ($timeout) {
return {
restrict: 'A',
scope: {
autoAction: '<',
},
link: function (scope, element, attr) {
const _el = element[0];
for (const func in scope.autoAction) {
if (!scope.autoAction.hasOwnProperty(func)) {
continue;
}
scope.$watch(`autoAction['${func}']`, (newVal, oldVal) => {
if (newVal !== oldVal) {
$timeout(() => {
_el[func]();
});
}
});
}
}
}
});
Um diese Frage zu beantworten, setzen Sie die Variable bei der Initialisierung (vorzugsweise) im Controller oder als ng-init:
<input ng-init="autofocus=true" auto-action="{'focus': autofocus}">
Einfach Kaffee einwerfen.
app.directive 'ngAltFocus', ->
restrict: 'A'
scope: ngAltFocus: '='
link: (scope, el, attrs) ->
scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv