【发布时间】:2013-02-20 23:07:07
【问题描述】:
如何自动大写 AngularJS 表单元素中输入字段中的第一个字符?
我已经看到了 jQuery 解决方案,但相信这必须在 AngularJS 中通过使用指令来完成。
【问题讨论】:
标签: angularjs input angularjs-directive capitalize
如何自动大写 AngularJS 表单元素中输入字段中的第一个字符?
我已经看到了 jQuery 解决方案,但相信这必须在 AngularJS 中通过使用指令来完成。
【问题讨论】:
标签: angularjs input angularjs-directive capitalize
是的,你需要定义一个指令并定义你自己的解析器函数:
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>
【讨论】:
请记住,并非所有事情都需要 Angular 解决方案。你在 jQuery 人群中看到了很多。他们喜欢使用昂贵的 jQuery 函数来做一些用纯 javascript 更简单或更容易做的事情。
因此,虽然您可能非常需要一个大写函数并且上述答案提供了这一点,但仅使用 css 规则“文本转换:大写”会更有效
<tr ng-repeat="(key, value) in item">
<td style="text-transform: capitalize">{{key}}</td>
<td>{{item}}</td>
</tr>
【讨论】:
您可以创建自定义过滤器“大写”并将其应用于您想要的任何字符串:
<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);
}
});
【讨论】:
使用 CSS :first-letter 伪类。
你需要把所有的东西都小写,然后只将大写应用于第一个字母
p{
text-transform: lowercase;
}
p:first-letter{
text-transform: uppercase;
}
【讨论】:
修改了他的代码以大写单词的每个第一个字符。如果你给'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
}
};
});
【讨论】:
我更喜欢过滤器和指令。这应该适用于光标移动:
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
【讨论】:
要修复光标问题(来自 Mark Rajcok 的解决方案), 您可以在方法的开头存储 element[0].selectionStart, 然后确保在返回之前将 element[0].selectionStart 和 element[0].selectionEnd 重置为存储的值。 这应该以角度捕获您的选择范围
【讨论】:
对 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()));
});
});
}
}
};
});
【讨论】:
生成指令:
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+
【讨论】:
以下是首字母大写的过滤器的代码笔: 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();}) : '';
}
});
【讨论】:
除了纯 CSS 的答案之外,您始终可以使用 Twitter Bootstrap:
<td class="text-capitalize">
【讨论】:
以 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));
}
};
});
【讨论】:
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();
}
}
};
}]);
【讨论】:
您可以使用提供的大写过滤器。
【讨论】:
你可以使用纯 CSS:
input {
text-transform: capitalize;
}
【讨论】: