web-dev-qa-db-fra.com

Comment définir le focus sur le champ de saisie?

Quelle est la "manière angulaire" de mettre l'accent sur le champ de saisie dans AngularJS?

Des exigences plus spécifiques:

  1. Quand un Modal est ouvert, définissez le focus sur un <input> prédéfini à l'intérieur de ce modal.
  2. À chaque fois que <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.

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

Plunker

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

Plunker


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.

561
Mark Rajcok

(EDIT: j'ai ajouté une solution mise à jour sous cette explication)

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:

Utilisez un événement, la fonctionnalité oubliée de Angular.

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.


Solution mise à jour

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.

Voici une démo rapide Plunk

Usage

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

La source

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

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

234
ecancil

HTML a un attribut autofocus.

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

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

87
Rayron Victor

Vous pouvez également utiliser la fonctionnalité jqlite intégrée à angular.

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

60
JordanC

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.

52
Sanjeev Singh

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

Documents relatifs à la directive AngularJS complète: https://docs.angularjs.org/api/ng/service/$compile

30
Cody Moniz

Voici ma solution originale:

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

Et le HTML:

<button ng-click="isVisible = !isVisible">Toggle input</button>
<input ng-show="isVisible" auto-focus="{{ isVisible }}" value="auto-focus on" />

Ce qu'il fait:

Il concentre l'entrée à mesure qu'il devient visible avec ng-show. Aucune utilisation de $ watch ou $ on ici.

17
Edhowler

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:

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

17
Umut Benzer

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

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

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

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

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/

6
broc.seib

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

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

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.

Usage

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

  afterLoad(notifyControllerEvent);
});

La source

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

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

3
Ludovic Guillaume

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.

3
ibaixas

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

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

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

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

2
Filipe Cotrim Melo

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

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"

2
Ofir Meguri

Si vous souhaitez définir le focus sur un élément particulier, vous pouvez utiliser l'approche ci-dessous.

  1. 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();
            });
        };
    });
    
  2. Injectez-le dans le contrôleur à partir duquel vous souhaitez appeler.

  3. Appelez ce service.

1
Rakesh Burbure

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!

1
xiaoma

C'est facile .. essayez ceci

html

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

javascript

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

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. 

0
user7339584

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é

0
johans

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

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

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
0
Talasan Nicholson