web-dev-qa-db-fra.com

Formater les numéros de téléphone et de carte de crédit dans AngularJS

Question 1 (mise en forme du numéro de téléphone):

Je dois formater un numéro de téléphone dans AngularJS mais il n'y a pas de filtre pour cela. Existe-t-il un moyen d'utiliser un filtre ou une devise pour formater 10 chiffres en (555) 555-5255? et toujours conserver le type de données du champ sous forme d'entier?

Deuxième question (masquage du numéro de carte de crédit):

J'ai un champ de carte de crédit mappé sur AngularJS, tel que:

<input type="text" ng-model="customer.creditCardNumber"> 

qui renvoie le nombre entier (4111111111111111). Je voudrais masquer avec xxx les 12 premiers chiffres et ne montrer que les 4 derniers. Je pensais utiliser un filtre: limite pour cela, mais je ne sais pas comment. Des idées? Est-il possible de formater également le nombre avec des tirets tout en conservant le type de données sous forme d'entier? sorte de 4111-1111-1111-1111.

68
J Castillo

De plus, si vous devez formater le numéro de téléphone uniquement en sortie, vous pouvez utiliser un filtre personnalisé comme celui-ci:

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

Ensuite, vous pouvez utiliser ce filtre dans votre modèle:

{{ phoneNumber | tel }}
<span ng-bind="phoneNumber | tel"></span>
144
kstep

J'ai créé un module AngularJS pour gérer moi-même ce problème de numéros de téléphone avec une directive personnalisée et un filtre associé.

exemple jsfiddle: http://jsfiddle.net/aberke/s0xpkgmq/

Exemple d'utilisation du filtre: <p>{{ phonenumberValue | phonenumber }}</p>

Code de filtre:

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

Exemple d'utilisation de la directive:

<phonenumber-directive placeholder="'Input phonenumber here'" model='myModel.phonenumber'></phonenumber-directive>

Code de la 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)">',
    };
}])

Code complet avec module et comment l’utiliser: https://Gist.github.com/aberke/042eef0f37dba1138f9e

18
aberke

Comme Shailbenq l'a suggéré, phoneformat est génial. 

Inclure le format du téléphone sur votre site Web. Créez un filtre pour le module angulaire ou votre application. 

angular.module('ng')
.filter('tel', function () {
    return function (phoneNumber) {
        if (!phoneNumber)
            return phoneNumber;

        return formatLocal('US', phoneNumber); 
    }
});

Ensuite, vous pouvez utiliser le filtre dans votre code HTML.

{{phone|tel}} 
OR
<span ng-bind="phone|tel"></span>

Si vous souhaitez utiliser le filtre dans votre contrôleur. 

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

enter image description here

J'ai aussi trouvé ce plugin JQuery facile à inclure dans votre application Angular (également avec bower: D) et vérifiant tous les codes de pays possibles avec leurs masques respectifs: intl-tel-input

Vous pouvez ensuite utiliser l'option validationScript afin de vérifier la validité de la valeur de l'entrée.

11
lightalex

Ceci est le moyen simple. Comme base, je l’ai prise à partir de http://codepen.io/rpdasilva/pen/DpbFf et j’ai fait quelques changements. Pour l'instant, le code est plus simplement . Et vous pouvez obtenir: dans le contrôleur - "4124561232", dans la vue "(412) 456-1232"

Filtre:

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

Et directive:

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
5
yavor.makc

Angular-ui a une directive pour masquer les entrées. C’est peut-être ce que vous voulez pour le masquage (malheureusement, la documentation n’est pas très bonne):

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

Je ne pense cependant pas que cela aidera à masquer le numéro de carte de crédit.

5
Narretz

Vous pouvez également vérifier input mask formter.

Ceci est une directive appelée ui-mask et qui fait également partie de angular-ui.utils library.

Ici fonctionne: Exemple live

Pour le moment où cet article a été écrit, il n’existait aucun exemple d’utilisation de cette directive; j’ai donc créé un très exemple simple pour montrer comment cette chose fonctionne dans la pratique.

5
Egel

Essayez d'utiliser phoneformat.js ( http://www.phoneformat.com/ ), vous ne pouvez pas formater un numéro de téléphone uniquement en fonction des paramètres régionaux (en-US, ja-JP, fr-FR, de-DE, etc. ) mais valide également le numéro de téléphone. Sa bibliothèque très robuste basée sur le projet googles libphonenumber.

2
shailbenq

J'ai pris la solution d'Aberke et l'ai modifiée à mon goût. 

  • Il produit un seul élément d'entrée
  • Il accepte éventuellement des extensions
  • Pour les numéros américains, il saute le code de pays en tête
  • Conventions de dénomination standard
  • Utilise la classe d'utiliser le code; ne constitue pas une classe
  • Permet l'utilisation de tout autre attribut autorisé sur un élément d'entrée

Mon Code Pen

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>

1
toddmo

J'ai modifié le code pour que le téléphone sorte dans ce format Valeur: +38 (095) 411-22-23 Ici, vous pouvez le vérifier saisir le lien ici

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

    };
});

Vous pouvez utiliser ng-pattern qui est plus facile et plus léger . http://tutorialzine.com/2014/12/learn-regular-expressions-in-20-minutes/ . Ici vous pouvez savoir à ce sujet , juste quelques mots significatifs , pas besoin de directive ou de filtre ,

1
Mohaimin Moin

Filtre simple qui ressemble à ceci (utilisez la classe numérique sur l'entrée et le caractère de filtre dans []):

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

0
Yej. M.

Trouvez Plunker pour formater les numéros de carte de crédit en utilisant la directive angularjs. Formater les numéros de carte en xxxxxxxxxxxxx3456 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";
  }]);
0
Sagar Bhosale

J'ai également résolu ce problème avec un filtre angulaire personnalisé, mais le mien tire parti des groupes de capture de regex et le code est donc très court. Je l'associe à un filtre stripNonNumeric distinct pour assainir l'entrée:

app.filter('stripNonNumeric', function() {
    return function(input) {
        return (input == null) ? null : input.toString().replace(/\D/g, '');
    }
});

Le filtre phoneFormat formate correctement un numéro de téléphone avec ou sans l'indicatif régional. (Je n'avais pas besoin d'un support de numéro international.)

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

Utilisez-les simplement:

<p>{{customer.phone | stripNonNumeric | phoneFormat}}</p>

La regex pour le filtre stripNonNumeric provenait de ici .

0
The DIMM Reaper

Vous devrez créer des contrôles de formulaire personnalisés (sous forme de directives) pour le numéro de téléphone et la carte de crédit. Voir la section "Implémentation du contrôle de formulaire personnalisé (à l'aide de ngModel)" sur la page formulaires .

Comme Narretz l'a déjà mentionné, la directive de masque d'Angular-ui devrait vous aider à démarrer.

0
Mark Rajcok

Voici comment j'ai créé la directive ssn qui vérifie le motif et j'ai utilisé 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);    
            };
        }
    };
}
0
Raghu Chaitanya