Форматирование номеров телефонов и кредитных карт в AngularJS
Вопрос первый (форматирование номера телефона):
мне нужно отформатировать номер телефона в AngularJS, но для него нет фильтра. Есть ли способ использовать фильтр или валюту для форматирования 10 цифр в (555) 555-5255
? и все же сохранить тип данных поля как целое число?
вопрос второй (маскировка номера кредитной карты):
у меня есть поле кредитной карты, которое отображается на AngularJS, например:
<input type="text" ng-model="customer.creditCardNumber">
что возвращает целое число (4111111111111111
). Я хотел бы замаскировать его с xxx первые 12 цифр и показать только последние 4. Я думал об использовании filter: limit для этого, но не ясно, как это сделать. Есть идеи? Есть ли способ также отформатировать число с помощью тире, но сохранить тип данных как целое число? вроде 4111-1111-1111-1111
.
17 ответов:
кроме того, если вам нужно отформатировать номер телефона только на выходе, вы можете использовать пользовательский фильтр, как этот:
angular.module('ng').filter('tel', function () { return function (tel) { if (!tel) { return ''; } var value = tel.toString().trim().replace(/^\+/, ''); if (value.match(/[^0-9]/)) { return tel; } var country, city, number; switch (value.length) { case 10: // +1PPP####### -> C (PPP) ###-#### country = 1; city = value.slice(0, 3); number = value.slice(3); break; case 11: // +CPPP####### -> CCC (PP) ###-#### country = value[0]; city = value.slice(1, 4); number = value.slice(4); break; case 12: // +CCCPP####### -> CCC (PP) ###-#### country = value.slice(0, 3); city = value.slice(3, 5); number = value.slice(5); break; default: return tel; } if (country == 1) { country = ""; } number = number.slice(0, 3) + '-' + number.slice(3); return (country + " (" + city + ") " + number).trim(); }; });
затем вы можете использовать этот фильтр в вашем шаблоне:
{{ phoneNumber | tel }} <span ng-bind="phoneNumber | tel"></span>
Я создал модуль AngularJS для обработки этой проблемы, касающейся телефонных номеров для себя с пользовательской директивой и сопутствующим фильтром.
jsfiddle пример:http://jsfiddle.net/aberke/s0xpkgmq/
пример использования фильтра :
<p>{{ phonenumberValue | phonenumber }}</p>
код фильтра:
.filter('phonenumber', function() { /* Format phonenumber as: c (xxx) xxx-xxxx or as close as possible if phonenumber length is not 10 if c is not '1' (country code not USA), does not use country code */ return function (number) { /* @param {Number | String} number - Number that will be formatted as telephone number Returns formatted number: (###) ###-#### if number.length < 4: ### else if number.length < 7: (###) ### Does not handle country codes that are not '1' (USA) */ if (!number) { return ''; } number = String(number); // Will return formattedNumber. // If phonenumber isn't longer than an area code, just show number var formattedNumber = number; // if the first character is '1', strip it out and add it back var c = (number[0] == '1') ? '1 ' : ''; number = number[0] == '1' ? number.slice(1) : number; // # (###) ###-#### as c (area) front-end var area = number.substring(0,3); var front = number.substring(3, 6); var end = number.substring(6, 10); if (front) { formattedNumber = (c + "(" + area + ") " + front); } if (end) { formattedNumber += ("-" + end); } return formattedNumber; }; });
директива пример использования:
<phonenumber-directive placeholder="'Input phonenumber here'" model='myModel.phonenumber'></phonenumber-directive>
код директивы:
.directive('phonenumberDirective', ['$filter', function($filter) { /* Intended use: <phonenumber-directive placeholder='prompt' model='someModel.phonenumber'></phonenumber-directive> Where: someModel.phonenumber: {String} value which to bind only the numeric characters [0-9] entered ie, if user enters 617-2223333, value of 6172223333 will be bound to model prompt: {String} text to keep in placeholder when no numeric input entered */ function link(scope, element, attributes) { // scope.inputValue is the value of input element used in template scope.inputValue = scope.phonenumberModel; scope.$watch('inputValue', function(value, oldValue) { value = String(value); var number = value.replace(/[^0-9]+/g, ''); scope.phonenumberModel = number; scope.inputValue = $filter('phonenumber')(number); }); } return { link: link, restrict: 'E', scope: { phonenumberPlaceholder: '=placeholder', phonenumberModel: '=model', }, // templateUrl: '/static/phonenumberModule/template.html', template: '<input ng-model="inputValue" type="tel" class="phonenumber" placeholder="{{phonenumberPlaceholder}}" title="Phonenumber (Format: (999) 9999-9999)">', }; }])
полный код с модулем и как использовать оно: https://gist.github.com/aberke/042eef0f37dba1138f9e
как предложил шейлбенк, phoneformat это круто.
включить формат телефона на вашем сайте. Создайте фильтр для углового модуля или вашего приложения.
angular.module('ng') .filter('tel', function () { return function (phoneNumber) { if (!phoneNumber) return phoneNumber; return formatLocal('US', phoneNumber); } });
затем вы можете использовать фильтр в HTML.
{{phone|tel}} OR <span ng-bind="phone|tel"></span>
Если вы хотите использовать фильтр в контроллере.
var number = '5553219876'; var newNumber = $filter('tel')(number);
Я также обнаружил, что плагин JQuery, который легко включить в ваше Угловое приложение (также с bower :D ) и который проверяет все возможные коды стран с их соответствующими масками : intl-tel-input
затем вы можете использовать
validationScript
опция для того, чтобы проверить правильность входного значения.
Angular-ui имеет директиву для маскирования ввода. Может быть, это то, что вы хотите для маскировки (к сожалению, документация не так уж и велика):
Я не думаю, что это поможет с запутыванием номера кредитной карты, хотя.
вы также можете проверить форматирование маски ввода.
это директива, и она называется
ui-mask
и частьюangular-ui.utils
библиотека.здесь работает: видео
на момент написания этого поста нет никаких примеров использования этой директивы, поэтому я сделал очень простой пример: чтобы продемонстрировать, как это работает в практиковать.
Это самый простой способ. Как основной я взял его из http://codepen.io/rpdasilva/pen/DpbFf, и сделал некоторые изменения. А пока код проще. И вы можете получить: в контроллере -"4124561232", в виде "(412) 456-1232"
фильтр:
myApp.filter 'tel', -> (tel) -> if !tel return '' value = tel.toString().trim().replace(/^\+/, '') city = undefined number = undefined res = null switch value.length when 1, 2, 3 city = value else city = value.slice(0, 3) number = value.slice(3) if number if number.length > 3 number = number.slice(0, 3) + '-' + number.slice(3, 7) else number = number res = ('(' + city + ') ' + number).trim() else res = '(' + city return res
и директива:
myApp.directive 'phoneInput', ($filter, $browser) -> require: 'ngModel' scope: phone: '=ngModel' link: ($scope, $element, $attrs) -> $scope.$watch "phone", (newVal, oldVal) -> value = newVal.toString().replace(/[^0-9]/g, '').slice 0, 10 $scope.phone = value $element.val $filter('tel')(value, false) return return
попробуйте использовать phoneformat.js (http://www.phoneformat.com/), Вы можете не только форматировать номер телефона на основе пользовательских локалей (en-US, ja-JP, fr-FR, de-DE и т. д.), но и проверять номер телефона. Его очень надежная библиотека, основанная на проекте googles libphonenumber.
вы можете использовать ng-pattern, который является более легким и более легким. http://tutorialzine.com/2014/12/learn-regular-expressions-in-20-minutes/. Здесь вы можете узнать об этом,,,просто некоторые значимые слова,,, не нуждается в какой-либо директиве или фильтре,,,,
Я принял решение aberke и изменить его, чтобы удовлетворить мой вкус.
- он производит один входной элемент
- он дополнительно принимает расширения
- для нас номера он пропускает ведущий код страны
- стандартные соглашения об именовании
- использует класс от использования кода; не составляет класс
- позволяет использовать любые другие атрибуты, разрешенные на входном элементе
мой код Пен
var myApp = angular.module('myApp', []); myApp.controller('exampleController', function exampleController($scope) { $scope.user = { profile: {HomePhone: '(719) 465-0001 x1234'}}; $scope.homePhonePrompt = "Home Phone"; }); myApp /* Intended use: <phone-number placeholder='prompt' model='someModel.phonenumber' /> Where: someModel.phonenumber: {String} value which to bind formatted or unformatted phone number prompt: {String} text to keep in placeholder when no numeric input entered */ .directive('phoneNumber', ['$filter', function ($filter) { function link(scope, element, attributes) { // scope.inputValue is the value of input element used in template scope.inputValue = scope.phoneNumberModel; scope.$watch('inputValue', function (value, oldValue) { value = String(value); var number = value.replace(/[^0-9]+/g, ''); scope.inputValue = $filter('phoneNumber')(number, scope.allowExtension); scope.phoneNumberModel = scope.inputValue; }); } return { link: link, restrict: 'E', replace: true, scope: { phoneNumberPlaceholder: '@placeholder', phoneNumberModel: '=model', allowExtension: '=extension' }, template: '<input ng-model="inputValue" type="tel" placeholder="{{phoneNumberPlaceholder}}" />' }; } ] ) /* Format phonenumber as: (aaa) ppp-nnnnxeeeee or as close as possible if phonenumber length is not 10 does not allow country code or extensions > 5 characters long */ .filter('phoneNumber', function() { return function(number, allowExtension) { /* @param {Number | String} number - Number that will be formatted as telephone number Returns formatted number: (###) ###-#### x ##### if number.length < 4: ### else if number.length < 7: (###) ### removes country codes */ if (!number) { return ''; } number = String(number); number = number.replace(/[^0-9]+/g, ''); // Will return formattedNumber. // If phonenumber isn't longer than an area code, just show number var formattedNumber = number; // if the first character is '1', strip it out var c = (number[0] == '1') ? '1 ' : ''; number = number[0] == '1' ? number.slice(1) : number; // (###) ###-#### as (areaCode) prefix-endxextension var areaCode = number.substring(0, 3); var prefix = number.substring(3, 6); var end = number.substring(6, 10); var extension = number.substring(10, 15); if (prefix) { //formattedNumber = (c + "(" + area + ") " + front); formattedNumber = ("(" + areaCode + ") " + prefix); } if (end) { formattedNumber += ("-" + end); } if (allowExtension && extension) { formattedNumber += ("x" + extension); } return formattedNumber; }; } );
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp" ng-controller="exampleController"> <p>Phone Number Value: {{ user.profile.HomePhone || 'null' }}</p> <p>Formatted Phone Number: {{ user.profile.HomePhone | phoneNumber }}</p> <phone-number id="homePhone" class="form-control" placeholder="Home Phone" model="user.profile.HomePhone" ng-required="!(user.profile.HomePhone.length || user.profile.BusinessPhone.length || user.profile.MobilePhone.length)" /> </div>
Я изменил код для вывода телефона в этом формате значение:+38 (095) 411-22-23 Здесь вы можете проверить это Введите описание ссылки здесь
var myApp = angular.module('myApp', []); myApp.controller('MyCtrl', function($scope) { $scope.currencyVal; }); myApp.directive('phoneInput', function($filter, $browser) { return { require: 'ngModel', link: function($scope, $element, $attrs, ngModelCtrl) { var listener = function() { var value = $element.val().replace(/[^0-9]/g, ''); $element.val($filter('tel')(value, false)); }; // This runs when we update the text field ngModelCtrl.$parsers.push(function(viewValue) { return viewValue.replace(/[^0-9]/g, '').slice(0,12); }); // This runs when the model gets updated on the scope directly and keeps our view in sync ngModelCtrl.$render = function() { $element.val($filter('tel')(ngModelCtrl.$viewValue, false)); }; $element.bind('change', listener); $element.bind('keydown', function(event) { var key = event.keyCode; // If the keys include the CTRL, SHIFT, ALT, or META keys, or the arrow keys, do nothing. // This lets us support copy and paste too if (key == 91 || (15 < key && key < 19) || (37 <= key && key <= 40)){ return; } $browser.defer(listener); // Have to do this or changes don't get picked up properly }); $element.bind('paste cut', function() { $browser.defer(listener); }); } }; }); myApp.filter('tel', function () { return function (tel) { console.log(tel); if (!tel) { return ''; } var value = tel.toString().trim().replace(/^\+/, ''); if (value.match(/[^0-9]/)) { return tel; } var country, city, num1, num2, num3; switch (value.length) { case 1: case 2: case 3: city = value; break; default: country = value.slice(0, 2); city = value.slice(2, 5); num1 = value.slice(5,8); num2 = value.slice(8,10); num3 = value.slice(10,12); } if(country && city && num1 && num2 && num3){ return ("+" + country+" (" + city + ") " + num1 +"-" + num2 + "-" + num3).trim(); } else if(country && city && num1 && num2) { return ("+" + country+" (" + city + ") " + num1 +"-" + num2).trim(); }else if(country && city && num1) { return ("+" + country+" (" + city + ") " + num1).trim(); }else if(country && city) { return ("+" + country+" (" + city ).trim(); }else if(country ) { return ("+" + country).trim(); } }; });
вам нужно будет создать пользовательские элементы управления формы (как директивы) для номера телефона и кредитной карты. См. раздел "реализация пользовательского управления формой (с помощью ngModel)" на формы страница.
Как уже упоминалось Narretz, Angular-ui's директива маски должно помочь вам начать работу.
простой фильтр что-то вроде этого (используйте числовой класс на входном конце фильтра charchter в []):
<script type="text/javascript"> // Only allow number input $('.numeric').keyup(function () { this.value = this.value.replace(/[^0-9+-\.\,\;\:\s()]/g, ''); // this is filter for telefon number !!! });
вот как я создал директиву ssn, которая проверяет шаблон, и я использовал RobinHerbots
jquery.inputmask
angular.module('SocialSecurityNumberDirective', []) .directive('socialSecurityNumber', socialSecurityNumber); function socialSecurityNumber() { var jquery = require('jquery'); var inputmask = require("jquery.inputmask"); return { require: 'ngModel', restrict: 'A', priority: 1000, link: function(scope,element, attr, ctrl) { var jquery_element = jquery(element); jquery_element.inputmask({mask:"***-**-****",autoUnmask:true}); jquery_element.on('keyup paste focus blur', function() { var val = element.val(); ctrl.$setViewValue(val); ctrl.$render(); }); var pattern = /^\d{9}$/; var newValue = null; ctrl.$validators.ssnDigits = function(value) { newValue = element.val(); return newValue === '' ? true : pattern.test(newValue); }; } }; }
я решил эту проблему с помощью пользовательского углового фильтра, но мой использует группы захвата регулярных выражений, и поэтому код действительно короткий. Я соединяю его с отдельным
stripNonNumeric
фильтр для очистки входных данных:app.filter('stripNonNumeric', function() { return function(input) { return (input == null) ? null : input.toString().replace(/\D/g, ''); } });
The
phoneFormat
фильтр правильно форматирует номер телефона с кодом города. (Мне не нужна была поддержка международных номеров.)app.filter('phoneFormat', function() { //this establishes 3 capture groups: the first has 3 digits, the second has 3 digits, the third has 4 digits. Strings which are not 7 or 10 digits numeric will fail. var phoneFormat = /^(\d{3})?(\d{3})(\d{4})$/; return function(input) { var parsed = phoneFormat.exec(input); //if input isn't either 7 or 10 characters numeric, just return input return (!parsed) ? input : ((parsed[1]) ? '(' + parsed[1] + ') ' : '') + parsed[2] + '-' + parsed[3]; } });
использовать их просто:
<p>{{customer.phone | stripNonNumeric | phoneFormat}}</p>
регулярное выражение для пришел из здесь.
найти Планкер для форматирования номеров кредитных карт С помощью директивы angularjs. Форматирование номеров карт в формате xxxxxxxxxxxx3456 Fromat.
angular.module('myApp', []) .directive('maskInput', function() { return { require: "ngModel", restrict: "AE", scope: { ngModel: '=', }, link: function(scope, elem, attrs) { var orig = scope.ngModel; var edited = orig; scope.ngModel = edited.slice(4).replace(/\d/g, 'x') + edited.slice(-4); elem.bind("blur", function() { var temp; orig = elem.val(); temp = elem.val(); elem.val(temp.slice(4).replace(/\d/g, 'x') + temp.slice(-4)); }); elem.bind("focus", function() { elem.val(orig); }); } }; }) .controller('myCtrl', ['$scope', '$interval', function($scope, $interval) { $scope.creditCardNumber = "1234567890123456"; }]);