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