Quelle est la "manière angulaire" de mettre l'accent sur le champ de saisie dans AngularJS?
Des exigences plus spécifiques:
<input>
prédéfini à l'intérieur de ce modal.<input>
devient visible (par exemple en cliquant sur un bouton), définissez son focus sur celui-ci.J'ai essayé de remplir la première condition with autofocus
, mais cela ne fonctionne que lorsque le modal est ouvert pour la première fois, et uniquement dans certains navigateurs (par exemple dans Firefox, cela ne fonctionne pas).
Toute aide serait appréciée.
- Lorsqu'un modal est ouvert, activez une <entrée> prédéfinie dans ce modal.
Définissez une directive et faites-la regarder une propriété/un déclencheur pour qu'il sache quand concentrer l'élément:
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));
});
}
};
}]);
Le délai d'attente $ semble être nécessaire pour donner le temps de rendu modal.
'2.' À chaque fois que <entrée> devient visible (par exemple en cliquant sur un bouton), mettez le focus dessus.
Créez une directive essentiellement comme celle ci-dessus. Observez une propriété de portée et quand elle devient vraie (définissez-la dans votre gestionnaire ng-click), exécutez element[0].focus()
. Selon votre cas d'utilisation, vous aurez peut-être besoin d'un délai d'attente de $ pour celui-ci:
<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;
//});
}
});
}
};
});
Mise à jour 7/2013: j'ai déjà vu quelques personnes utiliser les directives de portée isolées d'origine, puis avoir des problèmes avec les champs d'entrée incorporés (c'est-à-dire, un champ d'entrée dans le modal). Une directive sans nouvelle portée (ou éventuellement une nouvelle portée enfant) devrait atténuer quelque peu la douleur. Donc, ci-dessus, j'ai mis à jour la réponse pour ne pas utiliser les portées d'isolement. Voici la réponse originale:
Réponse originale pour 1., à l'aide d'un oscilloscope isolé:
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 .
Réponse originale pour 2. en utilisant un oscilloscope isolé:
<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 .
Puisque nous devons réinitialiser la propriété trigger/focusInput dans la directive, '=' est utilisé pour la liaison de données bidirectionnelle. Dans la première directive, "@" était suffisant. Notez également que lorsque vous utilisez '@', nous comparons la valeur de déclenchement à "true" car @ donne toujours une chaîne.
Mark Rajcok est l'homme ... et sa réponse est une réponse valable, mais elle a avait un défaut (désolé Mark) ...
... Essayez d'utiliser le booléen pour faire la mise au point sur l'entrée, puis brouillez l'entrée, puis essayez de l'utiliser pour focaliser à nouveau l'entrée. Cela ne fonctionnera que si vous réinitialisez le booléen sur false, puis $ digest, puis le réinitialisez sur true. Même si vous utilisez une comparaison de chaîne dans votre expression, vous serez obligé de changer la chaîne en quelque chose d'autre, $ digest, puis de la modifier. (Ce problème a été résolu avec le gestionnaire d'événements Blur.)
Je propose donc cette solution alternative:
JavaScript aime les événements après tout. Les événements sont intrinsèquement liés, et mieux encore, vous évitez d'ajouter une autre surveillance $ à votre $ digest.
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on(attr.focusOn, function(e) {
elem[0].focus();
});
};
});
Alors maintenant, vous pouvez l'utiliser comme ceci:
<input type="text" focus-on="newItemAdded" />
et ensuite n'importe où dans votre application ...
$scope.addNewItem = function () {
/* stuff here to add a new item... */
$scope.$broadcast('newItemAdded');
};
C'est génial parce que vous pouvez faire toutes sortes de choses avec quelque chose comme ça. D'une part, vous pouvez vous lier à des événements qui existent déjà. D'autre part, vous commencez à faire des choses intelligentes en faisant en sorte que différentes parties de votre application publient des événements auxquels d'autres parties de votre application peuvent s'abonner.
Quoi qu'il en soit, ce type de chose me crie "événementiel". Je pense qu'en tant que développeurs angulaires, nous essayons très fort de marteler des chevilles en forme de scope dans des trous en forme d'événement.
Est-ce la meilleure solution? Je ne sais pas. C'est la solution a.
Après le commentaire de @ ShimonRachlenko ci-dessous, j'ai légèrement modifié ma méthode. Maintenant, j'utilise une combinaison d'un service et d'une directive qui gère un événement "en coulisses":
Autre que cela, c'est le même principe décrit ci-dessus.
<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);
});
}
});
J'ai trouvé certaines des autres réponses trop compliquées alors que tout ce dont vous avez vraiment besoin, c'est
app.directive('autoFocus', function($timeout) {
return {
restrict: 'AC',
link: function(_scope, _element) {
$timeout(function(){
_element[0].focus();
}, 0);
}
};
});
l'utilisation est
<input name="theInput" auto-focus>
Nous utilisons le délai d’attente pour laisser les éléments restituer dans le dom, même s’il est égal à zéro, il attend au moins cela - ainsi, cela fonctionne dans les modaux et autres
HTML a un attribut autofocus
.
<input type="text" name="fname" autofocus>
Vous pouvez également utiliser la fonctionnalité jqlite intégrée à angular.
angular.element('.selector').trigger('focus');
Cela fonctionne bien et un moyen angulaire de se concentrer contrôle de l'entrée
angular.element('#elementId').focus()
Bien que ce ne soit pas une façon purement angulaire de faire la tâche, la syntaxe suit le style angulaire. Jquery joue un rôle indirectement et accède directement au DOM en utilisant Angular (jQLite => JQuery Light).
Si nécessaire, ce code peut facilement être placé dans une directive angulaire simple où l'élément est directement accessible.
Je ne pense pas que $ timeout soit un bon moyen de concentrer l'élément sur la création. Voici une méthode utilisant une fonctionnalité angulaire intégrée, extraite des profondeurs troubles des documents angulaires. Remarquez comment l'attribut "link" peut être divisé en "pre" et "post", pour les fonctions pre-link et post-link.
Exemple de travail: http://plnkr.co/edit/Fj59GB
// 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 />
Voici ma solution originale:
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()});
});
}
};
});
Et le HTML:
<button ng-click="isVisible = !isVisible">Toggle input</button>
<input ng-show="isVisible" auto-focus="{{ isVisible }}" value="auto-focus on" />
Il concentre l'entrée à mesure qu'il devient visible avec ng-show. Aucune utilisation de $ watch ou $ on ici.
J'ai écrit une directive de liaison contraignante bidirectionnelle, tout comme modèle récemment.
Vous pouvez utiliser la directive focus comme ceci:
<input focus="someFocusVariable">
Si vous introduisez une variable de portée true
dans la variable FocusVariable n'importe où dans votre contrôleur, l'entrée est ciblée. Et si vous voulez "brouiller" votre entrée, someFocusVariable peut être défini sur false. C'est comme la première réponse de Mark Rajcok mais avec une liaison à double sens.
Voici la directive:
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);
})
}
}
});
Usage:
<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>
Voici le violon:
Pour ceux qui utilisent Angular avec le plugin Bootstrap:
http://angular-ui.github.io/bootstrap/#/modal
Vous pouvez accéder à la promesse opened
de l'instance modale:
modalInstance.opened.then(function() {
$timeout(function() {
angular.element('#title_input').trigger('focus');
});
});
modalInstance.result.then(function ( etc...
J'ai trouvé utile d'utiliser une expression générale. De cette façon, vous pouvez faire des choses comme déplacer automatiquement le focus lorsque le texte saisi est valide
<button type="button" moo-focus-expression="form.phone.$valid">
Ou mise au point automatiquement lorsque l'utilisateur remplit un champ de longueur fixe
<button type="submit" moo-focus-expression="smsconfirm.length == 6">
Et bien sûr, concentration après charge
<input type="text" moo-focus-expression="true">
Le code de la directive:
.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
}
}
});
}
}
};
});
Au lieu de créer votre propre directive, il est possible d'utiliser simplement des fonctions javascript pour réaliser un focus.
Voici un exemple.
Dans le fichier html:
<input type="text" id="myInputId" />
Dans un fichier javascript, dans un contrôleur par exemple, où vous souhaitez activer le focus:
document.getElementById("myInputId").focus();
Ne pas ressusciter un zombie ou brancher ma propre directive (ok c'est exactement ce que je fais):
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
};
}
})();
Premièrement, une façon officielle de se concentrer est la feuille de route pour 1.1 . En attendant, vous pouvez écrire une directive pour implémenter le focus de la définition.
Deuxièmement, pour définir le focus sur un élément une fois qu'il est devenu visible, une solution de contournement est actuellement nécessaire. Retardez simplement votre appel à element focus () avec un $timeout
.
Étant donné que le même problème controller-modifies-DOM existe pour le focus, le flou et la sélection, je propose d’avoir une directive ng-target
:
<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>
Fil angulaire ici: http://goo.gl/ipsx4 , et plus de détails blogués ici: http://goo.gl/4rdZa
La directive suivante créera une fonction .focus()
dans votre contrôleur, comme spécifié par votre attribut ng-target
. (Cela crée également une .blur()
et une .select()
.) Démo: http://jsfiddle.net/bseib/WUcQX/
Un simple qui fonctionne bien avec les modaux:
.directive('focusMeNow', ['$timeout', function ($timeout)
{
return {
restrict: 'A',
link: function (scope, element, attrs)
{
$timeout(function ()
{
element[0].focus();
});
}
};
}])
Exemple
<input ng-model="your.value" focus-me-now />
Si vous vouliez juste un focus simple contrôlé par un ng-click.
Html:
<input ut-focus="focusTigger">
<button ng-click="focusTrigger=!focusTrigger" ng-init="focusTrigger=false"></button>
Directif:
'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 et Blesh ont d'excellentes réponses. Cependant, Mark's a un défaut que Blesh souligne (en plus d'être complexe à mettre en œuvre) et je pense que la réponse de Blesh comporte une erreur sémantique dans la création d'un service qui consiste spécifiquement à envoyer une demande de focus au serveur alors retarder l'événement jusqu'à ce que toutes les directives soient à l'écoute.
Voici donc ce que j'ai fini par faire, ce qui vole beaucoup de la réponse de Blesh mais maintient la sémantique de l'événement de contrôleur et le service "après chargement" séparés.
Cela permet à l'événement de contrôleur d'être facilement accroché pour des choses autres que la focalisation d'un élément spécifique et permet également de surcharger la fonctionnalité "après le chargement" uniquement si elle est nécessaire, ce qui peut ne pas être le cas dans de nombreux cas.
<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);
}
});
Ceci est également possible d'utiliser ngModelController
. Travailler avec 1.6+ (je ne sais pas avec les anciennes versions).
HTML
<form name="myForm">
<input type="text" name="myText" ng-model="myText">
</form>
JS
$scope.myForm.myText.$$element.focus();
-
NB: Selon le contexte, vous devrez peut-être intégrer une fonction de délai d'attente.
N.B.²: Lorsque vous utilisez controllerAs
, c'est presque la même chose. Il suffit de remplacer name="myForm"
par name="vm.myForm"
et dans JS, vm.myForm.myText.$$element.focus();
.
Vous pouvez simplement créer une directive qui force le focus sur l'élément décoré sur postLinking:
angular.module('directives')
.directive('autoFocus', function() {
return {
restrict: 'AC',
link: function(_scope, _element) {
_element[0].focus();
}
};
});
Puis dans votre html:
<input type="text" name="first" auto-focus/> <!-- this will get the focus -->
<input type="text" name="second"/>
Cela fonctionnerait pour les éléments modaux et ng-si basculés, pas pour ng-show, car postLinking concerne uniquement le traitement HTML.
Probablement la solution la plus simple sur l’ère ES6.
L'ajout de la directive one-line suivante rend l'attribut "autofocus" HTML effectif sur Angular.js.
.directive('autofocus', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())}))
Maintenant, vous pouvez simplement utiliser la syntaxe de mise au point automatique HTML5 comme:
<input type="text" autofocus>
La directive suivante a fait l'affaire pour moi. Utilisez le même attribut HTML autofocus pour la saisie.
.directive('autofocus', [function () {
return {
require : 'ngModel',
restrict: 'A',
link: function (scope, element, attrs) {
element.focus();
}
};
}])
Juste un débutant ici, mais j’étais capable de le faire fonctionner dans un ui.bootstrap.modal avec cette directive:
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();
});
}
});
}
};
});
et dans la méthode $ modal.open, j’ai utilisé ce qui suit pour indiquer l’élément sur lequel le focus doit être placé:
var d = $modal.open({
controller : function($scope, $modalInstance) {
...
$scope.idToFocus = "cancelaAteste";
}
...
});
sur le modèle, j'ai ceci:
<input id="myInputId" focus />
Si vous utilisez modalInstance et que vous avez l'objet, vous pouvez utiliser "then" pour effectuer des actions après avoir ouvert le modal. Si vous n'utilisez pas modalInstance et que vous avez codé en dur pour ouvrir le modal, vous pouvez utiliser l'événement. Le timeout $ n'est pas une bonne solution.
Vous pouvez faire (Bootstrap3):
$("#" + modalId).on("shown.bs.modal", function() {
angular.element("[name='name']").focus();
});
À modalInstance, vous pouvez consulter la bibliothèque pour savoir comment exécuter le code après une ouverture modale.
N'utilisez pas $ timeout comme ceci, le $ timeout peut être 0, 1, 10, 30, 50, 200 ou plus, cela dépend de l'ordinateur client et du processus d'ouverture modal.
N'utilisez pas $ timeout, laissez la méthode vous dire quand vous pouvez vous concentrer;)
J'espère que cette aide! :)
Je modifie la directive focusMe de Mark Rajcok pour qu'elle fonctionne dans un seul élément.
HTML:
<input focus-me="myInputFocus" type="text">
dans AngularJs Controller:
$scope.myInputFocus= true;
Directive AngulaJS:
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);
}
});
}
};
});
Toute la réponse précédente ne fonctionne pas si l'élément de focus souhaité est injecté dans un modèle de directive . La directive suivante s'adapte à la fois à l'élément simple ou à l'élément injecté de directive (je l'ai écrite dans TypeScript ). il accepte le sélecteur pour l'élément interne focalisable. si vous avez juste besoin de vous concentrer sur l'élément self, n'envoyez aucun paramètre de sélecteur à la directive:
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());
}
exemple d'utilisation pour élément simple:
<button tabindex="0" focus-on-load />
exemple d'utilisation pour élément interne (généralement pour un élément injecté dynamique tel que directive avec modèle):
<my-directive focus-on-load="input" />
vous pouvez utiliser n'importe quel sélecteur jQuery au lieu de "entrée"
Si vous souhaitez définir le focus sur un élément particulier, vous pouvez utiliser l'approche ci-dessous.
Créez un service appelé focus
.
angular.module('application')
.factory('focus', function ($timeout, $window) {
return function (id) {
$timeout(function () {
var element = $window.document.getElementById(id);
if (element)
element.focus();
});
};
});
Injectez-le dans le contrôleur à partir duquel vous souhaitez appeler.
Appelez ce service.
Je veux contribuer à cette discussion après avoir cherché une meilleure solution et ne pas l'avoir trouvée, devant la créer à la place.
Critères: 1. La solution doit être indépendante de la portée du contrôleur parent pour augmenter la capacité de réutilisation . 2. Évitez l’utilisation de $ watch pour surveiller certaines conditions, c’est lent, cela augmente la taille de la boucle de digestion et rend le test plus difficile . 3. Evitez $ timeout ou $ scope. $ Apply () pour déclencher une boucle de digestion . 4. Un élément d'entrée est présent dans l'élément où la directive est utilisée ouverte.
C'est la solution que j'ai le plus aimé:
Directif:
.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>
J'espère que cela aidera quelqu'un là-bas!
C'est facile .. essayez ceci
html
<select id="ddl00">
<option>"test 01"</option>
</select>
javascript
document.getElementById("ddl00").focus();
vous pouvez utiliser la directive ci-dessous qui donne une valeur booléenne en entrée HTML pour se concentrer dessus ...
//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" />
Vous pouvez même définir une fonction de votre contrôleur sur la valeur de la directive ngFocusattirer l'attention sur le code ci-dessous ...
<!-- html file -->
<input type="text" ng-focus="myFunc()" />
//controller file
$scope.myFunc=function(){
if(condition){
return true;
}else{
return false;
}
}
cette directive à se produire lorsque la page html est rendue.
Je pense que la directive est inutile. Utilisez les attributs HTML id et class pour sélectionner l'élément requis et demandez au service d'utiliser document.getElementById ou document.querySelector pour appliquer le focus (ou des équivalents jQuery).
Le balisage correspond à des directives HTML/angulaires standard avec un ID/classes ajouté pour la sélection.
<input id="myInput" type="text" ng-model="myInputModel" />
Le contrôleur diffuse un événement
$scope.$emit('ui:focus', '#myInput');
Dans l'interface utilisateur, service querySelector - s'il y a plusieurs correspondances (par exemple en raison de la classe), il ne renverra que la première
$rootScope.$on('ui:focus', function($event, selector){
var elem = document.querySelector(selector);
if (elem) {
elem.focus();
}
});
Vous voudrez peut-être utiliser $ timeout () pour forcer un cycle de résumé
Vous ne savez pas vraiment si compter sur le délai d'attente est une bonne idée, mais cela fonctionne pour ng-repeat car ce code s'exécute APRÈS que angularjs mette à jour le DOM afin de vous assurer que tous les objets sont présents:
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();
});
}]);
Appel par programme de n'importe quelle action sur l'élément: click (), focus (), select () ...
Usage:
<a href="google.com" auto-action="{'click': $scope.autoclick, 'focus': $scope.autofocus}">Link</a>
Directif:
/**
* 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]();
});
}
});
}
}
}
});
Pour répondre à cette question, définissez la variable à l’initialisation (de préférence) dans le contrôleur ou sous la forme ng-init:
<input ng-init="autofocus=true" auto-action="{'focus': autofocus}">
Je viens de jeter un peu de café.
app.directive 'ngAltFocus', ->
restrict: 'A'
scope: ngAltFocus: '='
link: (scope, el, attrs) ->
scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv