it-swarm.com.de

Wie kann der Fokus auf das Eingabefeld gesetzt werden?

Was ist der "winkelige Weg", um den Fokus auf das Eingabefeld in AngularJS zu setzen?

Spezifischere Anforderungen:

  1. Wenn ein Modal geöffnet ist, setzen Sie den Fokus auf einen vordefinierten <input> in diesem Modal.
  2. Jedes Mal, wenn <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.

727
Misha Moroshko
  1. 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));
            });
        }
    };
}]);

Plunker

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;
          //});
        }
      });
    }
  };
});

Plunker


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.

561
Mark Rajcok

(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 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:

Verwenden Sie ein Ereignis, die vergessene Funktion von Angular.

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.


Aktualisierte 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

Verwendungszweck

<input type="text" focus-on="focusMe"/>
app.controller('MyCtrl', function($scope, focus) {
    focus('focusMe');
});

Quelle

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);
    });
  }
});
258
Ben Lesh

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

234
ecancil

HTML hat ein Attribut autofocus.

<input type="text" name="fname" autofocus>

http://www.w3schools.com/tags/att_input_autofocus.asp

87
Rayron Victor

Sie können auch die in angle integrierte jqlite-Funktionalität verwenden.

angular.element('.selector').trigger('focus');

60
JordanC

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.

52
Sanjeev Singh

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

30
Cody Moniz

Hier ist meine ursprüngliche Lösung:

plunker

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" />

Was es macht:

Es fokussiert die Eingabe, sobald sie mit ng-show sichtbar wird. Keine Verwendung von $ watch oder $ on hier.

17
Edhowler

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:

http://fiddle.jshell.net/ubenzer/9FSL4/8/

17
Umut Benzer

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...
10
BPH

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
                        }
                    }
                });
            }
        }
    };
});
7
winry

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();
7
user3657103

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
        };
    }
})();
7
Jon Hieb

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/

6
broc.seib

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 />
4
Shawn Dotey

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();
                });
            });
        }
    }
});
4
TOBlender

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.

Verwendungszweck

<input type="text" focus-on="controllerEvent"/>
app.controller('MyCtrl', function($scope, afterLoad) {
  function notifyControllerEvent() {
      $scope.$broadcast('controllerEvent');
  }

  afterLoad(notifyControllerEvent);
});

Quelle

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);
  }
});
3
joshperry

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();.

3

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.

3
ibaixas

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>
3
Tsuneo Yoshioka

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();
        }
    };
}])
2
Kishore Relangi

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 />
2
pitervergara

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! :)

2

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);
                }
            });
        }
    };
});
2
Mohamad Khani

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.

2
Ofir Meguri

Wenn Sie den Fokus auf ein bestimmtes Element setzen möchten, können Sie den folgenden Ansatz verwenden.

  1. 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();
            });
        };
    });
    
  2. Injizieren Sie es in den Controller, von dem aus Sie anrufen möchten.

  3. Rufen Sie diesen Dienst an.

1
Rakesh Burbure

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!

1
xiaoma

Es ist einfach ... probiere es aus

html

<select id="ddl00">  
 <option>"test 01"</option>  
</select>

Javascript

document.getElementById("ddl00").focus();
1

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. 

0
user7339584

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

0
johans

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();
        });
    }]);
0
Alex

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}">
0
Mesco

Einfach Kaffee einwerfen.

app.directive 'ngAltFocus', ->
    restrict: 'A'
    scope: ngAltFocus: '='
    link: (scope, el, attrs) ->
        scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv
0