Dar formato a los números de teléfono y tarjeta de crédito en AngularJS

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:

  

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 .

    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 }}  

    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:

    {{ phonenumberValue | phonenumber }}

    {{ phonenumberValue | phonenumber }}

    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:

      

    Código directivo:

     .directive('phonenumberDirective', ['$filter', function($filter) { /* Intended use:  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: '', }; }]) 

    Código completo con módulo y cómo usarlo: https://gist.github.com/aberke/042eef0f37dba1138f9e

    Como sugirió shailbenq, el formato del teléfono 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  

    Si quieres usar el filtro en tu controlador.

     var number = '5553219876'; var newNumber = $filter('tel')(number); 

    enter image description here

    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.

    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):

    http://angular-ui.github.com/

    Sin embargo, no creo que esto ayude a ofuscar el número de la tarjeta de crédito.

    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.

    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 

    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.

    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 ,,,,

    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

    Mi pluma 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:  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: '' }; } ] ) /* 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; }; } ); 
      

    Phone Number Value: {{ user.profile.HomePhone || 'null' }}

    Formatted Phone Number: {{ user.profile.HomePhone | phoneNumber }}

    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(); } }; }); 

    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 formularios .

    Como ya mencionó Narretz, la directiva Mask de Angular-ui debería ayudarlo a comenzar.

    Filtro simple algo como esto (use la clase numérica en el filtro de entrada de entrada charchter en []):

      

    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); }; } }; } 

    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:

     

    {{customer.phone | stripNonNumeric | phoneFormat}}

    La expresión regular para el filtro stripNonNumeric vino de aquí .

    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"; }]); 

    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:

    {{ value|number:2 }}