Comment autocapitaliser le premier caractère d'un champ de saisie dans un élément de formulaire AngularJS?
J'ai déjà vu la solution jQuery, mais je pense que cela doit être fait différemment dans AngularJS en utilisant une directive.
Oui, vous devez définir une directive et définir votre propre fonction d'analyse:
myApp.directive('capitalizeFirst', function($parse) {
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
var capitalize = function(inputValue) {
if (inputValue === undefined) { inputValue = ''; }
var capitalized = inputValue.charAt(0).toUpperCase() +
inputValue.substring(1);
if(capitalized !== inputValue) {
modelCtrl.$setViewValue(capitalized);
modelCtrl.$render();
}
return capitalized;
}
modelCtrl.$parsers.Push(capitalize);
capitalize($parse(attrs.ngModel)(scope)); // capitalize initial value
}
};
});
HTML:
<input type="text" ng-model="obj.name" capitalize-first>
S'il vous plaît rappelez-vous que tout n'a pas besoin d'une solution angulaire. Vous voyez cela souvent avec la foule de jQuery; ils aiment utiliser des fonctions jQuery coûteuses pour faire des choses plus simples ou plus faciles à faire avec du javascript pur.
Donc, bien que vous ayez très bien besoin d’une fonction de capitalisation et que les réponses précédentes donnent cela, il sera beaucoup plus efficace d’utiliser simplement la règle css "text-transform: capitalize"
<tr ng-repeat="(key, value) in item">
<td style="text-transform: capitalize">{{key}}</td>
<td>{{item}}</td>
</tr>
Vous pouvez créer un filtre personnalisé 'capitalize' et l'appliquer à la chaîne de votre choix:
<div ng-controller="MyCtrl">
{{aString | capitalize}} !
</div>
Code JavaScript pour le filtre:
var app = angular.module('myApp',[]);
myApp.filter('capitalize', function() {
return function(input, scope) {
return input.substring(0,1).toUpperCase()+input.substring(1);
}
});
Je préférerais un filtre et une directive. Cela devrait fonctionner avec le mouvement du curseur:
app.filter('capitalizeFirst', function () {
return function (input, scope) {
var text = input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase();
return text;
}
});
app.directive('capitalizeFirst', ['$filter', function ($filter) {
return {
require: 'ngModel',
link: function (scope, element, attrs, controller) {
controller.$parsers.Push(function (value) {
var transformedInput = $filter('capitalizeFirst')(value);
if (transformedInput !== value) {
var el = element[0];
el.setSelectionRange(el.selectionStart, el.selectionEnd);
controller.$setViewValue(transformedInput);
controller.$render();
}
return transformedInput;
});
}
};
}]);
Voici un violon
Modifié son code pour mettre en majuscule chaque premier caractère de Word. Si vous donnez ' john doe ', la sortie est ' John Doe '
myApp.directive('capitalizeFirst', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
var capitalize = function(inputValue) {
var capitalized = inputValue.split(' ').reduce(function(prevValue, Word){
return prevValue + Word.substring(0, 1).toUpperCase() + Word.substring(1) + ' ';
}, '');
if(capitalized !== inputValue) {
modelCtrl.$setViewValue(capitalized);
modelCtrl.$render();
}
return capitalized;
}
modelCtrl.$parsers.Push(capitalize);
capitalize(scope[attrs.ngModel]); // capitalize initial value
}
};
});
Utilisez le code CSS: pseudo-classe en première lettre.
Vous devez tout mettre en minuscule et après avoir appliqué la majuscule à la première lettre
p{
text-transform: lowercase;
}
p:first-letter{
text-transform: uppercase;
}
Voici un exemple: http://jsfiddle.net/AlexCode/xu24h/
Pour résoudre le problème du curseur (d'où la solution de Mark Rajcok), Vous pouvez stocker l'élément [0] .selectionStart au début de votre méthode, Puis vous assurer de réinitialiser l'élément [0] .selectionStart et l'élément [0 ] .selectionEnd à la valeur stockée avant le retour . Cela devrait capturer votre plage de sélection en angulaire
Commentaire sur la solution Mark Rajcok: lorsque vous utilisez $ setViewValue, vous déclenchez à nouveau les analyseurs syntaxiques et les validateurs. Si vous ajoutez une instruction console.log au début de votre fonction de capitalisation, vous la verrez imprimée deux fois.
Je propose la solution de directive suivante (où ngModel est facultatif):
.directive('capitalize', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
var capitalize = function (inputValue) {
return (inputValue || '').toUpperCase();
}
if(ngModel) {
ngModel.$formatters.Push(capitalize);
ngModel._$setViewValue = ngModel.$setViewValue;
ngModel.$setViewValue = function(val){
ngModel._$setViewValue(capitalize(val));
ngModel.$render();
};
}else {
element.val(capitalize(element.val()));
element.on("keypress keyup", function(){
scope.$evalAsync(function(){
element.val(capitalize(element.val()));
});
});
}
}
};
});
En plus des réponses CSS uniquement, vous pouvez toujours utiliser Twitter Bootstrap :
<td class="text-capitalize">
Voici un code pour un filtre qui capitalise la première lettre: http://codepen.io/WinterJoey/pen/sfFaK
angular.module('CustomFilter', []).
filter('capitalize', function() {
return function(input, all) {
return (!!input) ? input.replace(/([^\W_]+[^\s-]*) */g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}) : '';
}
});
Construire à partir de la solution de Mark Rajcok; Il est important de considérer que la directive n'évalue que lorsque le champ de saisie est engagé, sinon vous obtiendrez des messages d'erreur jusqu'à ce que le champ de saisie contienne le 1er caractère . Solution facile avec quelques conditions: aller avec ça: https://jsfiddle.net/Ely_Liberov/Lze14z4g/2/
.directive('capitalizeFirst', function(uppercaseFilter, $parse) {
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
var capitalize = function(inputValue) {
if (inputValue != null) {
var capitalized = inputValue.charAt(0).toUpperCase() +
inputValue.substring(1);
if (capitalized !== inputValue) {
modelCtrl.$setViewValue(capitalized);
modelCtrl.$render();
}
return capitalized;
}
};
var model = $parse(attrs.ngModel);
modelCtrl.$parsers.Push(capitalize);
capitalize(model(scope));
}
};
});
Le problème avec les réponses css-ony est que le modèle angulaire n'est pas mis à jour avec la vue. En effet, css n'applique de style qu'après le rendu.
La directive suivante met à jour le modèle ET se souvient de l'emplacement des curseurs
app.module.directive('myCapitalize', [ function () {
'use strict';
return {
require: 'ngModel',
restrict: "A",
link: function (scope, elem, attrs, modelCtrl) {
/* Watch the model value using a function */
scope.$watch(function () {
return modelCtrl.$modelValue;
}, function (value) {
/**
* Skip capitalize when:
* - the value is not defined.
* - the value is already capitalized.
*/
if (!isDefined(value) || isUpperCase(value)) {
return;
}
/* Save selection position */
var start = elem[0].selectionStart;
var end = elem[0].selectionEnd;
/* uppercase the value */
value = value.toUpperCase();
/* set the new value in the modelControl */
modelCtrl.$setViewValue(value);
/* update the view */
modelCtrl.$render();
/* Reset the position of the cursor */
elem[0].setSelectionRange(start, end);
});
/**
* Check if the string is defined, not null (in case of Java object usage) and has a length.
* @param str {string} The string to check
* @return {boolean} <code>true</code> when the string is defined
*/
function isDefined(str) {
return angular.isDefined(str) && str !== null && str.length > 0;
}
/**
* Check if a string is upper case
* @param str {string} The string to check
* @return {boolean} <code>true</code> when the string is upper case
*/
function isUpperCase(str) {
return str === str.toUpperCase();
}
}
};
}]);