How to autocapitalize the first character in an input field inside an AngularJS form element?
I saw the jQuery solution already, but believe this has to be done differently in AngularJS by using a directive.
How to autocapitalize the first character in an input field inside an AngularJS form element?
I saw the jQuery solution already, but believe this has to be done differently in AngularJS by using a directive.
Yes, you need to define a directive and define your own parser function:
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>
$watch
in the controller? Assuming one only needs to use it one time. –
Thunder $asyncValidators
or ng-model-options="{ debounce: 1000 }"
. –
Wakeful Please remember that not everything needs an Angular solution. You see this a lot with the jQuery crowd; they like to use expensive jQuery functions to do things that are simpler or easier to do with pure javascript.
So while you might very well need a capitalize function and the above answers provide that, it's going to be a lot more efficient to just use the css rule "text-transform: capitalize"
<tr ng-repeat="(key, value) in item">
<td style="text-transform: capitalize">{{key}}</td>
<td>{{item}}</td>
</tr>
You can create a custom filter 'capitalize' and apply it to any string you want:
<div ng-controller="MyCtrl">
{{aString | capitalize}} !
</div>
JavaScript code for filter:
var app = angular.module('myApp',[]);
myApp.filter('capitalize', function() {
return function(input, scope) {
return input.substring(0,1).toUpperCase()+input.substring(1);
}
});
Use the CSS :first-letter pseudo class.
You need to put everything lowercase and after apply the uppercase only to the first letter
p{
text-transform: lowercase;
}
p:first-letter{
text-transform: uppercase;
}
Here's an example: http://jsfiddle.net/AlexCode/xu24h/
Modified his code to capitalize every first character of word. If you give 'john doe', output is '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
}
};
});
I would prefer a filter and directive. This should work with cursor movement:
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;
});
}
};
}]);
Here is a fiddle
To fix the cursor problem (from where Mark Rajcok's solution), you can store element[0].selectionStart at the beginning of your method, and then ensure to reset element[0].selectionStart and element[0].selectionEnd to the stored value before the return. This should capture your selection range in angular
Generate directive:
ng g directive capitalizeFirst
Update file 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);
}
}
}
Usage:
<input appCapitalizeFirst>
This code woks with Angular 11+
Comment to Mark Rajcok solution: when using $setViewValue, you trigger the parsers and validators again. If you add a console.log statement at the beginning of your capitalize function, you'll see it printed twice.
I propose the following directive solution (where ngModel is optional):
.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()));
});
});
}
}
};
});
Here's a codepen for a filter that capitalizes the first letter: 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();}) : '';
}
});
Further to the CSS-only answers, you could always use Twitter Bootstrap:
<td class="text-capitalize">
Building off Mark Rajcok's solution; It's important to consider that the directive evaluate only when the input field in engaged, otherwise you'll get error messages firing off until the input field has a 1st character. Easy fix with a few conditionals: A jsfiddle to go with that: 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));
}
};
});
The problem with css-ony answers is that the angular model is not updated with the view. This is because css only applies styling after rendering.
The following directive updates the model AND remembers the cursors location
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();
}
}
};
}]);
You can use the provided uppercase filter.
You could use pure css:
input {
text-transform: capitalize;
}
© 2022 - 2024 — McMap. All rights reserved.