ejemplo - Dar formato a los números de teléfono y tarjeta de crédito en AngularJS
ng-init (17)
Primera pregunta (formatear el número de teléfono):
Tengo que formatear un número de teléfono en AngularJS, pero no hay filtro para eso. ¿Hay alguna manera de usar filtro o moneda para formatear 10 dígitos en (555) 555-5255
? y aún conserva el tipo de datos del campo como un número entero?
Pregunta dos (número de tarjeta de crédito enmascarante):
Tengo un campo de tarjeta de crédito mapeado en AngularJS, como:
<input type="text" ng-model="customer.creditCardNumber">
que devuelve el número completo ( 4111111111111111
). Me gustaría enmascararlo con xxx los primeros 12 dígitos y solo mostrar los últimos 4. Estaba pensando en usar filtro: límite para esto pero no estoy tan claro como. ¿Algunas ideas? ¿Hay alguna manera de formatear también el número con guiones pero aún conservar el tipo de datos como un entero? tipo de 4111-1111-1111-1111
.
Inyecte el módulo ''xeditable'' en su aplicación angular (disponible gratuitamente):
var App = angular.module(''App'', [''xeditable'']);
Y luego use su función incorporada en su código HTML de la siguiente manera:
<div>{{ value|number:2 }}</div>
Además, si necesita formatear el número de teléfono solo en la salida, puede usar un 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();
};
});
Entonces puedes usar este filtro en tu plantilla:
{{ phoneNumber | tel }}
<span ng-bind="phoneNumber | tel"></span>
Angular-ui tiene una directiva para enmascarar la entrada. Tal vez esto es lo que quiere para enmascarar (desafortunadamente, la documentación no es tan buena):
Sin embargo, no creo que esto ayude a ofuscar el número de la tarjeta de crédito.
Como sugirió shailbenq, el phoneformat es increíble.
Incluya el formato del teléfono en su sitio web. Crea un filtro para el módulo angular o tu aplicación.
angular.module(''ng'')
.filter(''tel'', function () {
return function (phoneNumber) {
if (!phoneNumber)
return phoneNumber;
return formatLocal(''US'', phoneNumber);
}
});
Entonces puedes usar el filtro en tu HTML.
{{phone|tel}}
OR
<span ng-bind="phone|tel"></span>
Si quieres usar el filtro en tu controlador.
var number = ''5553219876'';
var newNumber = $filter(''tel'')(number);
Creé un módulo AngularJS para manejar este problema con respecto a los números telefónicos para mí con una directiva personalizada y el filtro correspondiente.
ejemplo jsfiddle: http://jsfiddle.net/aberke/s0xpkgmq/
Ejemplo de uso del filtro: <p>{{ phonenumberValue | phonenumber }}</p>
<p>{{ phonenumberValue | phonenumber }}</p>
Código de 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;
};
});
Ejemplo de uso de directiva:
<phonenumber-directive placeholder="''Input phonenumber here''" model=''myModel.phonenumber''></phonenumber-directive>
Código directivo:
.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 con módulo y cómo usarlo: https://gist.github.com/aberke/042eef0f37dba1138f9e
Encuentre Plunker para formatear números de tarjeta de crédito usando la directiva angularjs. Formatee los números de tarjeta en 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";
}]);
Esta es la forma en que creé la directiva ssn que busca el patrón y he usado 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);
};
}
};
}
Esta es la manera simple. Como básico, lo tomé de http://codepen.io/rpdasilva/pen/DpbFf , y realicé algunos cambios. Por ahora el código es más simple. Y puede obtener: en el controlador - " 4124561232 ", en vista " (412) 456-1232 "
Filtrar:
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
Y directiva:
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
Filtro simple algo como esto (use la clase numérica en el filtro de entrada de entrada charchter en []):
<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 !!!
});
Intente usar phoneformat.js ( http://www.phoneformat.com/ ), no solo puede formatear el número de teléfono según las configuraciones regionales del usuario (en-US, ja-JP, fr-FR, de-DE, etc.) sino que también valida el número de teléfono. Su biblioteca muy robusta basada en el proyecto googles libphonenumber.
Modifiqué el código al teléfono de salida en este formato Valor: +38 (095) 411-22-23 Aquí puede verificarlo ingrese la descripción del enlace aquí
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();
}
};
});
Puede usar ng-pattern que es más fácil y más ligero. http://tutorialzine.com/2014/12/learn-regular-expressions-in-20-minutes/ . Aquí puede saberlo, solo algunas palabras significativas, no necesita ninguna directiva o filtro ,,,,
También puede verificar el formateador de máscara de entrada .
Esta es una directiva y se llama ui-mask
y también es parte de angular-ui.utils
biblioteca angular-ui.utils
.
Aquí está trabajando: ejemplo en vivo
Para el momento de escribir este post, no hay ejemplos de cómo usar esta directiva, así que he hecho un ejemplo muy simple para demostrar cómo funciona esto en la práctica.
También resolví este problema con un filtro angular personalizado, pero el mío aprovecha los grupos de captura de expresiones regulares, por lo que el código es muy corto. Lo stripNonNumeric
con un filtro stripNonNumeric
separado para desinfectar la entrada:
app.filter(''stripNonNumeric'', function() {
return function(input) {
return (input == null) ? null : input.toString().replace(//D/g, '''');
}
});
El filtro phoneFormat
formatea correctamente un número de teléfono con o sin el código de área. (No necesitaba soporte de número internacional)
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];
}
});
Úselos simplemente:
<p>{{customer.phone | stripNonNumeric | phoneFormat}}</p>
La expresión regular para el filtro stripNonNumeric
vino de here .
Tendrá que crear controles de formulario personalizados (como directivas) para el número de teléfono y la tarjeta de crédito. Consulte la sección "Implementación del control de formulario personalizado (utilizando ngModel)" en la página de forms .
Como ya mencionó Narretz, la directiva Mask de Angular-ui debería ayudarlo a comenzar.
Tomé la solución de aberke y la modifiqué para adaptarla a mi gusto.
- Produce un solo elemento de entrada
- Opcionalmente acepta extensiones
- Para los números de EE. UU. Se salta el código de país principal
- Convenciones de nomenclatura estándar
- Utiliza clase desde el uso de código; no constituye una clase
- Permite el uso de cualquier otro atributo permitido en un elemento de entrada
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>
También encontré ese complemento JQuery que es fácil de incluir en su aplicación angular (también con bower: D) y que verifica todos los códigos de país posibles con sus respectivas máscaras: intl-tel-input
Luego puede usar la opción validationScript
para verificar la validez del valor de la entrada.