web-dev-qa-db-fra.com

Comment autocapitaliser le premier caractère d'un champ de saisie dans AngularJS?

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.

53
Federico Elles

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>

Fiddle

98
Mark Rajcok

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>
52
beardedlinuxgeek

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);
    }
});
23
Yuriy Shapovalov

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

4
Yoggi

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
     }
   };
});
4
Pradeep Mahdevu

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/

4
AlexCode

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

3
Barbara Hamde

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

En plus des réponses CSS uniquement, vous pouvez toujours utiliser Twitter Bootstrap :

<td class="text-capitalize">
1
dmvianna

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();}) : '';
    }
  });
1
Federico

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));
        }
       };
    });
0
Ely Liberov

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