- Lorsqu'un modal est ouvert, placez le focus sur une <entrée> prédéfinie à l'intérieur de ce modal.
Définissez une directive et faites-lui $ watch une propriété / 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));
});
}
};
}]);
Plunker
Le $ timeout semble être nécessaire pour donner le temps modal au rendu.
«2.» Chaque fois que <input> devient visible (par exemple en cliquant sur un bouton), définissez le focus dessus.
Créez une directive essentiellement comme celle ci-dessus. Observez une propriété de portée et lorsqu'elle devient vraie (définissez-la dans votre gestionnaire ng-click), exécutez element[0].focus()
. Selon votre cas d'utilisation, vous pouvez ou non avoir besoin d'un délai d'expiration $ 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;
//});
}
});
}
};
});
Plunker
Mise à jour 7/2013 : j'ai vu quelques personnes utiliser mes directives de portée origine et avoir ensuite des problèmes avec les champs de saisie intégrés (c'est-à-dire un champ de saisie dans le modal). Une directive sans nouvelle portée (ou éventuellement une nouvelle portée enfant) devrait atténuer une partie de la douleur. Donc, ci-dessus, j'ai mis à jour la réponse pour ne pas utiliser les étendues isolées. Voici la réponse originale:
Réponse originale pour 1., utilisant une portée isolée:
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., utilisant une portée isolée:
<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.
ng-model
sur le champ de saisie, la valeur du modèle est perdue lorsque j'utilise cette directive avec la portée isolate utilisée. Le problème ne se produit pas si j'essaie la version de Josh sans la portée isolée. Encore un débutant, et j'aimerais comprendre la différence. Voici un Plunker qui le montre.value != "true"
, et cela a semblé résoudre mon problème.(EDIT: j'ai ajouté une solution mise à jour sous cette explication)
Mark Rajcok est l'homme ... et sa réponse est une réponse valide, mais elle
aeu un défaut (désolé Mark) ...... Essayez d'utiliser le booléen pour vous concentrer sur l'entrée, puis brouillez l'entrée, puis essayez de l'utiliser pour recentrer l'entrée. Cela ne fonctionnera que si vous réinitialisez le booléen sur false, puis $ digest, puis réinitialisez-le sur true. Même si vous utilisez une comparaison de chaînes dans votre expression, vous serez obligé de remplacer la chaîne par quelque chose d'autre, $ digest, puis de la modifier à nouveau.(Ce problème a été résolu avec le gestionnaire d'événements flou.)Je propose donc cette solution alternative:
Utilisez un événement, la fonctionnalité oubliée d'Angular.
JavaScript aime les événements après tout. Les événements sont intrinsèquement mal couplés, et encore mieux, vous évitez d'ajouter une autre $ watch à votre $ digest.
Alors maintenant, vous pouvez l'utiliser comme ceci:
puis n'importe où dans votre application ...
C'est génial car vous pouvez faire toutes sortes de choses avec quelque chose comme ça. D'une part, vous pouvez lier des événements qui existent déjà. Pour une autre chose, vous commencez à faire quelque chose d'intelligent en demandant à différentes parties de votre application de publier des événements auxquels d'autres parties de votre application peuvent s'abonner.
Quoi qu'il en soit, ce genre de chose me crie «en fonction des événements». Je pense qu'en tant que développeurs Angular, nous essayons vraiment de marteler les chevilles en forme de $ scope dans des trous de forme d'événement.
Est-ce la meilleure solution? Je ne sais pas. C'est une solution.
Solution mise à jour
Après le commentaire de @ ShimonRachlenko ci-dessous, j'ai légèrement changé ma méthode. Maintenant, j'utilise une combinaison d'un service et d'une directive qui gère un événement "en coulisses":
En dehors de cela, c'est le même principe décrit ci-dessus.
Voici une démo rapide Plunk
Usage
La source
la source
$broadcast
avec$timeout
si vous souhaitez que cela fonctionne lors de l'entrée dans le contrôleur. Sinon, belle solution.J'ai trouvé que certaines des autres réponses étaient trop compliquées alors que tout ce dont vous avez vraiment besoin est
l'utilisation est
Nous utilisons le délai d'attente pour laisser les choses dans le dom rendre, même s'il est nul, il attend au moins cela - de cette façon cela fonctionne dans les modaux et ainsi de suite
la source
ng-click
: disons que cliquer sur un bouton ang-click="showInput = !showInput
sur votre entrée. Ensuite, sur votre entrée réelle, ajoutezng-if="showInput"
. Le fait de basculer le bouton fera exécuter la directive à chaque fois. J'avais un problème avec cela pendant que j'utilisaisng-show
ce qui est la mauvaise approche.HTML a un attribut
autofocus
.http://www.w3schools.com/tags/att_input_autofocus.asp
la source
Vous pouvez également utiliser la fonctionnalité jqlite intégrée à angular.
angular.element('.selector').trigger('focus');
la source
Looking up elements via selectors is not supported by jqLite!
Cela fonctionne bien et une manière angulaire de concentrer le contrôle d'entrée
Ce n'est pas une façon angulaire pure de faire la tâche, mais 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 simple directive angulaire où l'élément est directement accessible.
la source
Looking up elements via selectors is not supported by jqLite!
angular.element
devient un wrapper pour$() / jQuery()
. Donc, sans cela, cela ne fonctionnera pas, et vous utilisez simplement jQuery de toute façon (mais corrigez-moi si je me trompe)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, creusée dans les profondeurs obscures des documents angulaires. Remarquez comment l'attribut "link" peut être divisé en "pré" et "post", pour les fonctions de pré-lien et de post-lien.
Exemple de travail: http://plnkr.co/edit/Fj59GB
Documents sur la directive AngularJS complète: https://docs.angularjs.org/api/ng/service/$compile
la source
Voici ma solution originale:
plongeur
Et le HTML:
Ce qu'il fait:
Il concentre l'entrée lorsqu'elle devient visible avec ng-show. Pas d'utilisation de $ watch ou $ ici.
la source
J'ai écrit une directive de focus contraignant dans les deux sens, tout comme le modèle récemment.
Vous pouvez utiliser la directive focus comme ceci:
Si vous créez une variable d'étendue FocusVariable
true
n'importe où dans votre contrôleur, l'entrée devient focalisé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 bidirectionnelle.Voici la directive:
Usage:
Voici le violon:
http://fiddle.jshell.net/ubenzer/9FSL4/8/
la source
Pour ceux qui utilisent Angular avec le plugin Bootstrap:
http://angular-ui.github.io/bootstrap/#/modal
Vous pouvez vous accrocher à la
opened
promesse de l'instance modale:la source
$timeout
avec50ms
est dans le besoin au lieu de0
.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
Ou se concentrer automatiquement lorsque l'utilisateur remplit un champ de longueur fixe
Et bien sûr, se concentrer après la charge
Le code de la directive:
la source
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
la source
Tout d'abord, une façon officielle de se concentrer est sur la feuille de route pour 1.1 . Pendant ce temps, vous pouvez écrire une directive pour implémenter la définition du focus.
Deuxièmement, pour définir le focus sur un élément après qu'il soit devenu visible, une solution de contournement est actuellement nécessaire. Il suffit de retarder votre appel à focus élément () avec un
$timeout
.Parce que le même problème de contrôleur-modifie-DOM existe pour le focus, le flou et la sélection, je propose d'avoir une
ng-target
directive: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
.focus()
fonction à l'intérieur de votre contrôleur comme spécifié par votreng-target
attribut. (Cela crée un.blur()
et un.select()
aussi.) Démo: http://jsfiddle.net/bseib/WUcQX/la source
ngFocus
semble être un moyen de gérer lesfocus
événements, pas un moyen de mettre l'accent sur un élément.Au lieu de créer votre propre directive, il est possible d'utiliser simplement des fonctions javascript pour effectuer un focus.
Voici un exemple.
Dans le fichier html:
Dans un fichier javascript, dans un contrôleur par exemple, où vous souhaitez activer le focus:
la source
Si vous vouliez juste une mise au point simple qui était contrôlée par un ng-clic.
Html:
Directif:
la source
Un simple qui fonctionne bien avec les modaux:
Exemple
la source
Vous pouvez simplement créer une directive qui force le focus sur l'élément décoré sur postLinking:
Puis dans votre html:
Cela fonctionnerait pour les modaux et les éléments ng-if toggled, pas pour ng-show puisque postLinking ne se produit que sur le traitement HTML.
la source
Mark et Blesh ont d'excellentes réponses; cependant, Mark's a un défaut que Blesh souligne (en plus d'être complexe à implémenter), et je pense que la réponse de Blesh a une erreur sémantique dans la création d'un service qui consiste spécifiquement à envoyer une demande de focus au frontend alors que tout ce dont il avait besoin était un moyen de retarder l'événement jusqu'à ce que toutes les directives écoutent.
Voici donc ce que j'ai fini par faire, qui vole beaucoup de la réponse de Blesh mais garde la sémantique de l'événement du contrôleur et le service "après chargement" séparés.
Cela permet à l'événement du contrôleur d'être facilement accroché à d'autres choses que la simple focalisation d'un élément spécifique et permet également d'engager la surcharge de la fonctionnalité "après chargement" uniquement si elle est nécessaire, ce qui peut ne pas être le cas dans de nombreux cas.
Usage
La source
la source
Ceci est également possible à utiliser
ngModelController
. Travailler avec 1.6+ (ne sais pas avec les anciennes versions).HTML
JS
-
NB: Selon le contexte, vous devrez peut-être encapsuler une fonction de temporisation.
NB²: Lors de l'utilisation
controllerAs
, c'est presque la même chose. Il suffit de remplacername="myForm"
avecname="vm.myForm"
et JS,vm.myForm.myText.$$element.focus();
.la source
Probablement, la solution la plus simple à l'ère ES6.
L'ajout de la directive liner suivante rend l'attribut HTML «autofocus» efficace sur Angular.js.
Maintenant, vous pouvez simplement utiliser la syntaxe de mise au point automatique HTML5 comme:
la source
.directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
Juste un débutant ici, mais j'ai pu le faire fonctionner dans un ui.bootstrap.modal avec cette directive:
et dans la méthode $ modal.open, j'ai utilisé ce qui suit pour indiquer l'élément où le focus doit être placé:
sur le modèle j'ai ceci:
la source
La directive suivante a fait l'affaire pour moi. Utilisez le même attribut html de mise au point automatique pour la saisie.
la source
Si vous utilisez modalInstance et que vous avez l'objet, vous pouvez utiliser "alors" pour effectuer des actions après l'ouverture du modal. Si vous n'utilisez pas le modalInstance, et codé en dur pour ouvrir le modal, vous pouvez utiliser l'événement. Le délai d'expiration $ n'est pas une bonne solution.
Vous pouvez faire (Bootstrap3):
Sur modalInstance, vous pouvez consulter la bibliothèque pour savoir comment exécuter le code après l'ouverture du modal.
N'utilisez pas $ timeout comme celui-ci, le $ timeout peut être 0, 1, 10, 30, 50, 200 ou plus, cela dépendra de l'ordinateur client et du processus pour ouvrir le modal.
N'utilisez pas $ timeout, laissez la méthode vous dire quand vous pouvez vous concentrer;)
J'espère que cette aide! :)
la source
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 à un élément simple ou à un élément injecté de directive (je l'ai écrit en tapuscrit ). il accepte le sélecteur pour l'élément focalisable interne. si vous avez juste besoin de concentrer l'élément self - n'envoyez aucun paramètre de sélection à la directive:
}
exemple d'utilisation d'un élément simple:
exemple d'utilisation de l'élément interne (généralement pour un élément injecté dynamique comme une directive avec un modèle):
vous pouvez utiliser n'importe quel sélecteur jQuery au lieu de "input"
la source
J'édite la directive focusMe de Mark Rajcok pour travailler sur plusieurs focus dans un seul élément.
HTML:
dans AngularJs Controller:
Directive AngulaJS:
la source
Je veux contribuer à cette discussion après avoir cherché une meilleure solution et ne pas l'avoir trouvée, je dois 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 réutilisation. 2. Évitez d'utiliser $ watch pour surveiller certaines conditions, cela est à la fois lent, augmente la taille de la boucle de résumé et rend les tests plus difficiles. 3. Évitez $ timeout ou $ scope. $ Apply () pour déclencher une boucle de résumé. 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 appréciée:
Directif:
Html:
J'espère que cela aidera quelqu'un là-bas!
la source
C'est facile .. essayez ceci
html
javascript
la source
Si vous souhaitez mettre l'accent sur un élément particulier, vous pouvez utiliser l'approche ci-dessous.
Créez un service appelé
focus
.Injectez-le dans le contrôleur d'où vous souhaitez appeler.
Appelez ce service.
la source
Je pense que la directive est inutile. Utilisez l'ID HTML et les attributs de classe pour sélectionner l'élément requis et demandez au service d'utiliser document.getElementById ou document.querySelector pour appliquer le focus (ou les équivalents jQuery).
Le balisage est des directives HTML / angulaires standard avec des id / classes ajoutés pour la sélection
Le contrôleur diffuse l'événement
Dans l'interface utilisateur, le service utilise querySelector - s'il y a plusieurs correspondances (par exemple en raison de la classe), il ne renverra que la première
Vous voudrez peut-être utiliser $ timeout () pour forcer un cycle de résumé
la source
Je jette juste du café.
la source