Formate números de telefone e cartão de crédito em AngularJS
-
12-12-2019 - |
Pergunta
Pergunta um (formatação do número de telefone):
Estou tendo que formatar um número de telefone em AngularJS mas não existe filtro para isso.Existe uma maneira de usar filtro ou moeda para formatar 10 dígitos para (555) 555-5255
?e ainda preservar o tipo de dados do campo como inteiro?
Pergunta dois (mascarando o número do cartão de crédito):
Eu tenho um campo de cartão de crédito mapeado para AngularJS, como:
<input type="text" ng-model="customer.creditCardNumber">
que está retornando o número inteiro (4111111111111111
).Gostaria de mascarar com xxx os primeiros 12 dígitos e mostrar apenas os últimos 4.Eu estava pensando em usar filtro:limite para isso, mas não estou claro como.Alguma ideia?Existe uma maneira de formatar também o número com travessões, mas ainda manter o tipo de dados como número inteiro?tipo de 4111-1111-1111-1111
.
Solução
Além disso, se precisar formatar o número de telefone apenas na saída, você pode usar um filtro personalizado como este:
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();
};
});
Então você pode usar este filtro em seu modelo:
{{ phoneNumber | tel }}
<span ng-bind="phoneNumber | tel"></span>
Outras dicas
Eu criei um módulo AngularJS para lidar com esse problema relacionado a números de telefone com uma diretiva personalizada e um filtro de acompanhamento.
exemplo jsfiddle: http://jsfiddle.net/aberke/s0xpkgmq/
Exemplo de uso de filtro: <p>{{ phonenumberValue | phonenumber }}</p>
Código do filtro:
.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;
};
});
Exemplo de uso de diretiva:
<phonenumber-directive placeholder="'Input phonenumber here'" model='myModel.phonenumber'></phonenumber-directive>
Código da diretiva:
.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)">',
};
}])
Código completo com módulo e como usá-lo:https://gist.github.com/aberke/042eef0f37dba1138f9e
Como sugeriu Shailbenq, formato de telefone é incrível.
Inclua o formato de telefone em seu site.Crie um filtro para o módulo angular ou seu aplicativo.
angular.module('ng')
.filter('tel', function () {
return function (phoneNumber) {
if (!phoneNumber)
return phoneNumber;
return formatLocal('US', phoneNumber);
}
});
Então você pode usar o filtro em seu HTML.
{{phone|tel}}
OR
<span ng-bind="phone|tel"></span>
Se você quiser usar o filtro em seu controlador.
var number = '5553219876';
var newNumber = $filter('tel')(number);
Também descobri aquele plugin JQuery que é fácil de incluir no seu App Angular (também com bower :D ) e que verifica todos os códigos de países possíveis com suas respectivas máscaras:entrada intl-tel
Você pode então usar o validationScript
opção para verificar a validade do valor da entrada.
Angular-ui possui uma diretiva para mascarar entradas.Talvez seja isso que você deseja para mascarar (infelizmente, a documentação não é tão boa):
Não acho que isso ajude a ofuscar o número do cartão de crédito.
Você também pode verificar formatador de máscara de entrada.
Esta é uma directiva e chama-se ui-mask
e também faz parte angular-ui.utils
biblioteca.
Aqui está funcionando: Exemplo ao vivo
No momento em que escrevo este post não há nenhum exemplo de uso desta diretiva, então fiz uma pesquisa muito exemplo simples para demonstrar como isso funciona na prática.
Esta é a maneira simples.Como básico eu tirei de http://codepen.io/rpdasilva/pen/DpbFf, e fiz algumas alterações.Por enquanto o código é mais simples.E você pode obter:no controlador - "4124561232", em vista "(412) 456-1232"
Filtro:
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
E diretiva:
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
Tente usar phoneformat.js (http://www.phoneformat.com/), você pode não apenas formatar o número de telefone com base nas localidades do usuário (en-US, ja-JP, fr-FR, de-DE etc), mas também validar o número de telefone.Sua biblioteca muito robusta baseada no projeto libphonenumber do Google.
Você pode usar o padrão ng, que é mais fácil e mais leve.http://tutorialzine.com/2014/12/learn-regular-expressions-in-20-minutos/.Aqui você pode saber sobre isso,,,apenas algumas palavras significativas,,,não precisa de nenhuma diretiva ou filtro,,,,
Peguei a solução de aberke e modifiquei-a para se adequar ao meu gosto.
- Produz um único elemento de entrada
- Opcionalmente aceita extensões
- Para números dos EUA, ignora o código do país principal
- Convenções de nomenclatura padrão
- Usa classe de uso de código;não constitui uma aula
- Permite o uso de quaisquer outros atributos permitidos em um elemento de entrada
Meu Caneta de código
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>
Modifiquei o código para gerar telefone neste formato Valor: +38 (095) 411-22-23Aqui você pode conferir insira a descrição do link aqui
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();
}
};
});
Você precisará criar controles de formulário personalizados (como diretivas) para o número de telefone e o cartão de crédito.Consulte a seção "Implementando o controle de formulário personalizado (usando ngModel)" no formulários página.
Como Narretz já mencionou, o Angular-ui Diretiva de máscara deve ajudar você a começar.
Filtro simples mais ou menos assim (use a classe numérica no caractere do filtro final de entrada em []):
<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 !!!
});
Aqui está como criei a diretiva ssn que verifica o padrão e usei 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);
};
}
};
}
Resolvi esse problema também com um filtro Angular personalizado, mas o meu aproveita a captura de grupos de regex e, portanto, o código é muito curto.Eu emparelho com um separado stripNonNumeric
filter para higienizar a entrada:
app.filter('stripNonNumeric', function() {
return function(input) {
return (input == null) ? null : input.toString().replace(/\D/g, '');
}
});
O phoneFormat
filter formata corretamente um número de telefone com ou sem o código de área.(Eu não precisava de suporte para números internacionais.)
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];
}
});
Use-os simplesmente:
<p>{{customer.phone | stripNonNumeric | phoneFormat}}</p>
A regex para o stripNonNumeric
filtro veio de aqui.
Encontrar Plunker para formatar números de cartão de crédito usando a diretiva angularjs.Formate números de cartão em 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";
}]);
Injete o módulo 'xeditable' em seu aplicativo angular (disponível gratuitamente):
var App = angular.module('App', ['xeditable']);
E então use seu recurso integrado em seu código HTML da seguinte maneira:
<div>{{ value|number:2 }}</div>