Entrée autofocus attribut
J'ai des endroits dans mon code où j'ai ceci:
<input data-ng-disabled="SOME_SCOPE_VARIABLE" />
Je voudrais pouvoir l'utiliser comme ceci aussi:
<input data-ng-autofocus="SOME_SCOPE_VARIABLE" />
Ou encore mieux, imitant la façon dont ng-style est fait:
<input data-ng-attribute="{autofocus: SOME_SCOPE_VARIABLE}" />
Cela existe-t-il dans la version actuelle D'AngularJS? J'ai remarqué dans le code qu'il y a un BOOLEAN_ATTR qui obtient tous les attr que AngularJS supporte. Je ne veux pas modifier cela de peur de changer de version et d'oublier de mettre à jour.
9 réponses
Mise à Jour: AngularJS a maintenant un ngFocus
la directive qui évalue une expression sur focus, mais je le mentionne ici par souci d'exhaustivité.
La version actuelle D'AngularJS n'a pas de directive focus, mais elle est dans la feuille de route. Par coïncidence, nous étionsen train de parler de ceci sur la liste de diffusion hier, et j'ai trouvé ceci:
angular.module('ng').directive('ngFocus', function($timeout) {
return {
link: function ( scope, element, attrs ) {
scope.$watch( attrs.ngFocus, function ( val ) {
if ( angular.isDefined( val ) && val ) {
$timeout( function () { element[0].focus(); } );
}
}, true);
element.bind('blur', function () {
if ( angular.isDefined( attrs.ngFocusLost ) ) {
scope.$apply( attrs.ngFocusLost );
}
});
}
};
});
Qui fonctionne à partir d'une variable de portée comme vous l'avez demandé:
<input type="text" ng-focus="isFocused" ng-focus-lost="loseFocus()">
Voici un violon: http://jsfiddle.net/ANfJZ/39/
Vous pouvez le faire avec les liaisons d'attributs ngAttr intégrées.
<input ng-attr-autofocus="{{SOME_SCOPE_VARIABLE}}">
L'attribut autofocus sera ajouté si SOME_SCOPE_VARIABLE
est défini (même si c'est false
), et sera supprimé si c'est undefined
. Donc, je force les valeurs fausses à être undefined
.
$scope.SOME_SCOPE_VARIABLE = someVar || undefined;
Cette directive devrait faire l'affaire:
angular.module('utils.autofocus', [])
.directive('autofocus', ['$timeout', function($timeout) {
return {
restrict: 'A',
scope: {'autofocus':'='}
link : function($scope, $element) {
$scope.$watch 'autofocus', function(focus){
if(focus){
$timeout(function() {
$element[0].focus();
});
}
}
}
}
}]);
Prises à partir d'ici: https://gist.github.com/mlynch/dd407b93ed288d499778
scope.doFocus = function () {
$timeout(function () {
document.getElementById('you_input_id').focus();
});
};
Ce que j'ai fait est d'utiliser l'autofocus régulier sur mes entrées: <input autofocus>
Et puis je mets le focus sur la première entrée visible avec autofocus quand angular est prêt:
angular.element(document).ready(function() {
$('input[autofocus]:visible:first').focus();
});
J'espère que cela aide.
Je l'ai fait avec deux directives personnalisées, quelque chose comme ceci:
(function(angular) {
'use strict';
/* @ngInject */
function myAutoFocus($timeout) {
return {
restrict: 'A',
link: function(scope, element) {
$timeout(function() {
element[0].focus();
}, 300);
}
};
}
function myFocusable() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var focusMethodName = attrs.myFocusable;
scope[focusMethodName] = function() {
element[0].focus();
};
}
};
}
angular
.module('myFocusUtils', [])
.directive('myAutoFocus', myAutoFocus)
.directive('myFocusable', myFocusable);
}(angular));
Si vous ajoutez l'attribut my-auto-focus
à un élément, il recevra le focus après 300ms. j'ai mis la valeur à 300 au lieu de 0 pour laisser les autres composants asynchrones charger avant de définir le focus.
L'attribut my-focusable
créera une fonction dans la portée actuelle. Cette fonction définira le focus sur l'élément lorsqu'il est appelé. Comme cela crée quelque chose dans la portée, soyez prudent pour éviter de surcharger quelque chose.
De cette façon vous pas besoin d'ajouter quelque chose au cycle de digest D'Angular (watch
) et peut le faire entièrement dans la vue:
<input my-focusable="focusOnInput"></input>
<button ng-click="focusOnInput()">Click to focus</button>
J'ai créé un JSFiddle pour afficher la directive myFocusable
: http://jsfiddle.net/8shLj3jc/
Pour une raison que je ne sais pas, la directive myAutoFocus
ne fonctionne pas dans JSFiddle, mais cela fonctionne dans ma page.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<div ng-repeat="x in names">
<input ng-attr-focus={{$first}} value="{{x.name + ', ' + x.country }}" />
</div>
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('namesCtrl', function($scope) {
$scope.names = [
{name:'x1',country:'y1'},
{name:'x2',country:'y2'},
{name:'x3',country:'y3'}
];
});
myApp.directive("focus", function(){
return {
restrict: "A",
link: function link(scope, element, attrs) {
if(JSON.parse(attrs.focus)){
element[0].focus();
}
}
};
});
</script>
</body>
</html>
Avait créé la directive personnalisée ci-dessus pour l'un de mes cas d'utilisation.
- se concentre toujours sur le premier élément d'entrée.
- fonctionne pour les données ajax, les boutons retour/avant du navigateur.
- testé sur chrome et firefox (l'autofocus par défaut n'est pas pris en charge ici)
JSON.parse est utilisé pour analyser la chaîne "true" renvoyée de html à booléen true dans JS.
une autre façon d'utiliser attrs.focus === "true" si la condition.
Créez une directive comme celle-ci
.directive('autoFocus', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, $element) {
$timeout(function () {
$element[0].focus();
});
}
}
<input type="text" auto-focus class="form-control msd-elastic" placeholder="">
Donc, sans $ timeout, vous pouvez également utiliser la mise au point automatique comme ceci -
<input type="text" ng-show="{{condition}}" class='input-class'></input>
angular.element(document).ready(function(){
angular.element('.input-class')[0].focus();
});