Как autocapitalize первый символ в поле ввода на AngularJS?
Как autocapitalize первый символ в поле ввода внутри в AngularJS форма элемента?
Я уже видел решение jQuery, но считаю, что это должно быть сделано по-другому в AngularJS с помощью директивы.
14 ответов:
да, вам нужно определить директиву и определить свою собственную функцию парсера:
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>
пожалуйста, помните, что не все нуждается в угловые решения. Вы видите это много с толпой jQuery; они любят использовать дорогие функции jQuery, чтобы делать вещи, которые проще или легче сделать с чистым javascript.
поэтому, хотя вам может очень понадобиться функция capitalize, и приведенные выше ответы обеспечивают это, будет намного эффективнее просто использовать правило css "text-transform: capitalize"
<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; }
вот пример:http://jsfiddle.net/AlexCode/xu24h/
изменил свой код, чтобы заглавные буквы каждого первого символа слова. Если вы дадите'Вася Пупкин', выход 'Вася Пупкин'
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; }); } }; }]);
здесь скрипка
чтобы исправить проблему с курсором (откуда решение Марка Райкока), вы можете хранить элемент[0].selectionStart в начале вашего метода, а затем убедитесь, что сбросить элемент[0].selectionStart и элемент[0].selectionEnd к сохраненному значению перед возвратом. Это должно захватить ваш диапазон выбора в угловой
комментарий к решению Mark Rajcok: при использовании $setViewValue вы снова запускаете Парсеры и валидаторы. Если вы добавляете консоль.оператор log в начале функции capitalize вы увидите, что он напечатан дважды.
Я предлагаю следующее директивное решение (где 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())); }); }); } } }; });
вот кодовый ключ для фильтра, который заглавными буквами первой буквы: 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; важно учитывать, что директива оценивает только тогда, когда поле ввода включено, иначе вы получите сообщения об ошибках, срабатывающие до тех пор, пока поле ввода не будет иметь 1-го символа. Легко исправить с помощью нескольких условных обозначений: В 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(); } } }; }]);