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

Posted

技术标签:

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

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

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

【问题讨论】:

【参考方案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;

【讨论】:

OP 只想将输入中的第一个字母大写。此解决方案将每个单词大写 @ChrisBier,我认为您将大写与大写混淆了。 css-tricks.com/almanac/properties/t/text-transform

以上是关于如何自动大写AngularJS输入字段中的第一个字符?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 iOS Safari 输入标签中的自动大写?

如何在黑莓应用程序文本字段中启用自动大写、标点、文本功能?

在AngularJS中选择一个输入字段时如何禁用一个输入字段? (都使用相同的 ng 模型)

如何在AngularJS中大写和大写?

iphone:如何将我的文本字段的第一个字符大写?

AngularJS |如何将 Json 的数据发送到 Codeigniter 中的数据库