Formatieren Sie Telefon- und Kreditkartennummern in AngularJS


69

Frage eins (Formatierung der Telefonnummer):

Ich muss eine Telefonnummer in AngularJS formatieren, aber es gibt keinen Filter dafür. Gibt es eine Möglichkeit, Filter oder Währung zum Formatieren von 10 Ziffern zu verwenden (555) 555-5255? und trotzdem den Datentyp des Feldes als Ganzzahl beibehalten?

Frage zwei (Maskierung der Kreditkartennummer):

Ich habe ein Kreditkartenfeld, das AngularJS zugeordnet ist, wie:

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

Das gibt die ganze Nummer zurück ( 4111111111111111). Ich möchte es mit xxx die ersten 12 Ziffern maskieren und nur die letzten 4 anzeigen. Ich habe überlegt, filter: limit dafür zu verwenden, bin mir aber nicht sicher, wie. Irgendwelche Ideen? Gibt es eine Möglichkeit, die Zahl auch mit Bindestrichen zu formatieren und den Datentyp dennoch als Ganzzahl beizubehalten? irgendwie 4111-1111-1111-1111.


5
Telefonnummern und Kreditkartennummern sind komplizierte Konstrukte, die möglicherweise eine komplizierte Benutzeroberfläche erfordern. Sie alle verdienen ihre eigene Frage, anstatt sich in eine solche zu verwandeln.
Mark Amery

2
Zu Ihrer ersten Frage: Verwenden Sie in nicht numerischen Feldern keine Ganzzahl als Datentyp. Telefone, Postleitzahlen und Dokumentennummern sind nicht numerisch (Sie werden nie damit rechnen) und werden besser als Zeichenfolgen behandelt.
Marcos Lima

Antworten:


148

Wenn Sie die Telefonnummer nur bei der Ausgabe formatieren müssen, können Sie einen benutzerdefinierten Filter wie den folgenden verwenden:

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

Dann können Sie diesen Filter in Ihrer Vorlage verwenden:

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

Ich habe es als Geige versucht, aber es fehlt etwas, das ich nicht herausfinden kann. Hier ist es: jsfiddle.net/jorgecas99/S7aSj
J Castillo

5
klappt wunderbar! Es war meine Schuld, ich hatte einige Tippfehler drin. Hier ist die aktualisierte Geige: jsfiddle.net/jorgecas99/S7aSj
J Castillo

1
Die Funktion ist großartig. Kannst du den Filter in einer Eingabe verwenden? hatte keine Anwendung auf die Eingabe. dafür habe ich ui-mask verwendet und es ist weniger elegant: /
Dave Alperovich

J Castill, in Zeile 36 Ihrer Geige würde ich tun: Land = 1? "": Land;
Jade Hamel

1
Immer noch ein wenig kaputt für internationale Zahlen.
Roger Far

20

Ich habe ein AngularJS-Modul erstellt, um dieses Problem in Bezug auf Telefonnummern mit einer benutzerdefinierten Direktive und einem zugehörigen Filter für mich selbst zu lösen.

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

Anwendungsbeispiel für Filter: <p>{{ phonenumberValue | phonenumber }}</p>

Filtercode:

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

Anwendungsbeispiel für die Richtlinie:

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

Richtliniencode:

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

Vollständiger Code mit Modul und dessen Verwendung: https://gist.github.com/aberke/042eef0f37dba1138f9e


Wenn ich mein Formular speichere und wieder öffne, wird die Nummer nicht gespeichert. Haben Sie keine Ahnung, dass es passiert?
Neuling

13

Wie Shailbenq vorgeschlagen hat, ist das Telefonformat fantastisch.

Fügen Sie das Telefonformat in Ihre Website ein. Erstellen Sie einen Filter für das Winkelmodul oder Ihre Anwendung.

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

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

Dann können Sie den Filter in Ihrem HTML verwenden.

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

Wenn Sie den Filter in Ihrem Controller verwenden möchten.

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

außer für i18n bevorzuge ich AngularUIs ui.mask
Bernardo Dal Corno

11

Geben Sie hier die Bildbeschreibung ein

Ich fand auch das JQuery-Plugin, das einfach in Ihre Angular App aufzunehmen ist (auch mit bower: D) und das alle möglichen Ländercodes mit ihren jeweiligen Masken überprüft: intl-tel-input

Mit dieser validationScriptOption können Sie dann die Gültigkeit des Eingabewerts überprüfen.


Gibt es irgendwelche Optionen, um das JQuery-Plugin zu entfernen?
Syed Rasheed

5

Angular-ui hat eine Direktive zum Maskieren von Eingaben. Vielleicht möchten Sie dies zum Maskieren (leider ist die Dokumentation nicht so gut):

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

Ich denke jedoch nicht, dass dies bei der Verschleierung der Kreditkartennummer helfen wird.


Versuchen Sie dies zur Dokumentation: ng-newsletter.com/posts/angular-ui-utils.html . Ignorieren Sie den Teil mask.js und 'ui.mask'. Verwenden Sie stattdessen ui.utils.js und 'ui.utils', während Sie Abhängigkeiten hinzufügen.
Sidharth Panwar

Wenn die Dokumentation nicht so gut ist, geben Sie ein funktionierendes Beispiel, um dies zu überwinden. Vielen Dank.
Toddmo

5

Sie können auch den Eingabemaskenformatierer überprüfen .

Dies ist eine Direktive, die aufgerufen wird ui-maskund auch Teil der angular-ui.utilsBibliothek ist.

Hier funktioniert: Live-Beispiel

Zum Zeitpunkt des Schreibens dieses Beitrags gibt es keine Beispiele für die Verwendung dieser Richtlinie. Daher habe ich ein sehr einfaches Beispiel erstellt , um zu demonstrieren, wie dieses Ding in der Praxis funktioniert.



5

Dies ist der einfache Weg. Als Basis habe ich es von http://codepen.io/rpdasilva/pen/DpbFf genommen und einige Änderungen vorgenommen. Im Moment ist Code einfacher. Und Sie können erhalten: in Controller - " 4124561232 ", in Ansicht " (412) 456-1232 "

Filter:

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

Und Richtlinie:

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

2

Versuchen Sie es mit phoneformat.js ( http://www.phoneformat.com/ ). Sie können die Telefonnummer nicht nur basierend auf den Gebietsschemas der Benutzer (en-US, ja-JP, fr-FR, de-DE usw.) formatieren, sondern auch validiert die Telefonnummer. Seine sehr robuste Bibliothek basiert auf dem Google Libphonenumber-Projekt.


2

Ich habe den Code geändert, um das Telefon in diesem Format auszugeben. Wert: +38 (095) 411-22-23 Hier können Sie überprüfen, ob Sie hier eine Linkbeschreibung eingeben

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

    };
});


1

Ich nahm Aberkes Lösung und modifizierte sie nach meinem Geschmack.

  • Es wird ein einzelnes Eingabeelement erzeugt
  • Optional werden Erweiterungen akzeptiert
  • Bei US-Nummern wird der führende Ländercode übersprungen
  • Standard-Namenskonventionen
  • Verwendet Klasse aus der Verwendung von Code; macht keine Klasse aus
  • Ermöglicht die Verwendung anderer Attribute, die für ein Eingabeelement zulässig sind

Mein Codestift

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>


0

Sie müssen benutzerdefinierte Formularsteuerelemente (als Anweisungen) für die Telefonnummer und die Kreditkarte erstellen. Siehe Abschnitt "Implementieren einer benutzerdefinierten Formularsteuerung (mit ngModel)" auf der Formularseite .

Wie Narretz bereits erwähnt hat, sollte die Mask-Direktive von Angular-ui Ihnen den Einstieg erleichtern .


0

Einfacher Filter wie folgt (verwenden Sie die numerische Klasse für den Filter des Eingangsendes in []):

<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

Hier ist die Art und Weise, wie ich die ssn-Direktive erstellt habe, die nach dem Muster sucht, und RobinHerbots verwendet habe 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

Ich habe dieses Problem auch mit einem benutzerdefinierten Winkelfilter gelöst, aber meiner nutzt die Regex-Erfassungsgruppen und der Code ist daher sehr kurz. Ich kopple es mit einem separaten stripNonNumericFilter, um die Eingabe zu bereinigen:

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

Der phoneFormatFilter formatiert eine Telefonnummer mit oder ohne Vorwahl richtig. (Ich brauchte keine Unterstützung für internationale Nummern.)

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

Verwenden Sie sie einfach:

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

Die Regex für den stripNonNumericFilter kam von hier .


0

Finden Sie Plunker zum Formatieren von Kreditkartennummern mithilfe der AngularJS-Direktive. Formatieren Sie die Kartennummern in 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";
  }]);

0

Fügen Sie das Modul 'xeditable' in Ihre Winkel-App ein (frei verfügbar):

var App = angular.module('App', ['xeditable']);

Verwenden Sie dann die in Ihrem HTML-Code integrierte Funktion wie folgt:

<div>{{ value|number:2 }}</div>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.