【问题标题】:How to autocapitalize the first character in an input field in AngularJS?如何自动大写AngularJS输入字段中的第一个字符?
【发布时间】:2013-02-20 23:07:07
【问题描述】:

如何自动大写 AngularJS 表单元素中输入字段中的第一个字符?

我已经看到了 jQuery 解决方案,但相信这必须在 AngularJS 中通过使用指令来完成。

【问题讨论】:

    标签: angularjs input angularjs-directive capitalize


    【解决方案1】:

    是的,你需要定义一个指令并定义你自己的解析器函数:

    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

    【讨论】:

    • 您能否再解释一下这是如何工作的或提供文档链接?此外,如果您在开头键入一个小写字母并且该框不为空,则光标将移动到末尾,但如果您键入一个大写字符,它不会...
    • @JasonGoemaat, docs.angularjs.org/guide/forms#customvalidation 我对如何修复光标移动没有任何想法。
    • @JasonGoemaat 发生光标移动是因为内容被更改的文本替换(仅当第一个字母输入为非大写时才更改)。要解决此问题,您可以捕获选择范围并在设置后在新文本中重置新选择范围。有一个名为 Rangy (code.google.com/p/rangy) 的可爱库,如果你足够认真地修复它,它将帮助你解决这个问题。
    • scope[attrs.ngModel] 不适用于: 因为 attrs.ngModel 评估为“myObj.user .name" 所以 scope[attrs.ngModel] 的计算结果为 undefined。
    • @Andi,很好。我更新了答案和小提琴以使用 $parse,它将处理原始案例和您的场景。
    【解决方案2】:

    请记住,并非所有事情都需要 Angular 解决方案。你在 jQuery 人群中看到了很多。他们喜欢使用昂贵的 jQuery 函数来做一些用纯 javascript 更简单或更容易做的事情。

    因此,虽然您可能非常需要一个大写函数并且上述答案提供了这一点,但仅使用 css 规则“文本转换:大写”会更有效

    <tr ng-repeat="(key, value) in item">
        <td style="text-transform: capitalize">{{key}}</td>
        <td>{{item}}</td>
    </tr>
    

    【讨论】:

    • OP 只想将输入中的第一个字母大写。此解决方案将每个单词大写
    • 好主意,但这不一定适用于输入字段,如果提交(例如输入输入,单击保存),我只是被它咬了。
    • 就我而言,我遇到了这个问题,寻找“强制小写”的解决方案。感谢您发布此内容,即使它不是 OP 的完美解决方案。
    • 正是我所需要的!!谢谢!
    【解决方案3】:

    您可以创建自定义过滤器“大写”并将其应用于您想要的任何字符串:

     <div ng-controller="MyCtrl">
         {{aString | capitalize}} !
    </div>
    

    过滤器的JavaScript代码:

    var app = angular.module('myApp',[]);
    
    myApp.filter('capitalize', function() {
        return function(input, scope) {
            return input.substring(0,1).toUpperCase()+input.substring(1);
        }
    });
    

    【讨论】:

    • 我认为过滤器不能应用于输入字段。
    • 这不是很丢脸吗,@tamakisquare;我是来谷歌搜索的。
    • 一句中的多个单词怎么做?
    【解决方案4】:

    使用 CSS :first-letter 伪类。

    你需要把所有的东西都小写,然后只将大写应用于第一个字母

    p{
        text-transform: lowercase;
    }
    p:first-letter{
        text-transform: uppercase;
    }
    

    这是一个例子:http://jsfiddle.net/AlexCode/xu24h/

    【讨论】:

    • 不,恐怕不会。这适用于内容,而不适用于元素的特定属性。在输入上,恐怕你必须使用 javascript。
    【解决方案5】:

    修改了他的代码以大写单词的每个第一个字符。如果你给'john doe',输出是'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
         }
       };
    });
    

    【讨论】:

      【解决方案6】:

      我更喜欢过滤器和指令。这应该适用于光标移动:

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

      这是fiddle

      【讨论】:

        【解决方案7】:

        要修复光标问题(来自 Mark Rajcok 的解决方案), 您可以在方法的开头存储 element[0].selectionStart, 然后确保在返回之前将 element[0].selectionStart 和 element[0].selectionEnd 重置为存储的值。 这应该以角度捕获您的选择范围

        【讨论】:

        • 能否提供更多细节
        【解决方案8】:

        对 Mark Rajcok 解决方案的评论:使用 $setViewValue 时,您会再次触发解析器和验证器。如果您在大写函数的开头添加一个 console.log 语句,您会看到它打印了两次。

        我提出以下指令解决方案(其中 ngModel 是可选的):

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

        【讨论】:

          【解决方案9】:

          生成指令:

          ng g directive capitalizeFirst
          

          更新文件 capitalize-first.directive.ts:

          import {Directive, ElementRef, HostListener} from '@angular/core';
          
          @Directive({
            selector: '[appCapitalizeFirst]'
          })
          export class CapitalizeFirstDirective {
          
            constructor(private ref: ElementRef) {
            }
          
            @HostListener('input', ['$event'])
            onInput(event: any): void {
              if (event.target.value.length === 1) {
                const inputValue = event.target.value;
                this.ref.nativeElement.value = inputValue.charAt(0).toUpperCase() + inputValue.substring(1);
              }
            }
          
          }
          

          用法:

            <input appCapitalizeFirst>
          

          此代码适用于 Angular 11+

          【讨论】:

            【解决方案10】:

            以下是首字母大写的过滤器的代码笔: 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();}) : '';
                }
              });
            

            【讨论】:

              【解决方案11】:

              除了纯 CSS 的答案之外,您始终可以使用 Twitter Bootstrap

              <td class="text-capitalize">
              

              【讨论】:

                【解决方案12】:

                以 Mark Rajcok 的解决方案为基础;重要的是要考虑该指令仅在输入字段参与时评估,否则您将收到错误消息,直到输入字段具有第一个字符。 使用几个条件轻松修复: 一个与之配套的jsfiddle: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));
                        }
                       };
                    });
                

                【讨论】:

                  【解决方案13】:

                  css-ony 答案的问题是角度模型没有随视图更新。这是因为 css 仅在渲染后应用样式。

                  以下指令更新模型并记住光标位置

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

                  【讨论】:

                  • 这使整个文本大写。我只寻找首字母大写。并且光标保持在其位置
                  【解决方案14】:

                  您可以使用提供的大写过滤器。

                  http://docs.angularjs.org/api/ng.filter:uppercase

                  【讨论】:

                  • 我认为过滤器不能应用于输入字段。
                  • 大写全部大写。
                  【解决方案15】:

                  你可以使用纯 CSS:

                  input { text-transform: capitalize; }

                  【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-08-11
                  • 2015-07-24
                  • 1970-01-01
                  • 2017-11-03
                  • 2022-08-16
                  • 2014-02-12
                  • 1970-01-01
                  相关资源
                  最近更新 更多