问题一(格式化电话号码):

我必须在 AngularJS 中格式化电话号码,但没有过滤器。有没有办法使用过滤器或货币来格式化 10 位数字 (555) 555-5255?并且仍将字段的数据类型保留为整数?

问题二(隐藏信用卡号):

我有一个映射到 AngularJS 的信用卡字段,例如:

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

返回整数(4111111111111111)。我想用 xxx 屏蔽它的前 12 位数字,只显示最后 4 位。我正在考虑使用过滤器:对此有限制,但不清楚如何限制。有任何想法吗?有没有办法也用破折号格式化数字,但仍将数据类型保留为整数?有点 4111-1111-1111-1111.

有帮助吗?

解决方案

此外,如果需要仅在输出上格式化电话号码,则可以使用像这样的自定义过滤器:

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

然后,您可以在模板中使用此过滤器:

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

其他提示

我创建了一个AngularJS模块,以处理有关自定义指令和伴随过滤器的单个帖子的此问题。

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

过滤器用例: <p>{{ phonenumberValue | phonenumber }}</p>

过滤器代码:

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

指令用途示例:

<phonenumber-directive placeholder="'Input phonenumber here'" model='myModel.phonenumber'></phonenumber-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)">',
    };
}])
.

与模块的完整代码以及如何使用它: https://gist.github.com/aberke/042eef0f37dba1138f9e

作为shailbenq建议, phoneformat 很棒。

在您的网站中包含电话格式。为角模块或应用程序创建过滤器。

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

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

然后,您可以使用HTML中的过滤器。

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

如果要在控制器中使用过滤器。

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

我还发现,jQuery插件易于包含在你的Angular App(也是Bower:D)中,并用各自的面具检查所有可能的国家代码: Intl-tel-input

然后,您可以使用validationScript选项来检查输入值的有效性。

Angular-UI具有用于掩蔽输入的指令。也许这就是你想要的掩蔽(不幸的是,文档不是很大):

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

我不认为这将有助于混淆信用卡号码。

您还可以检查 输入掩码格式化程序.

这是一个指令,它被称为 ui-mask 而且它也是的一部分 angular-ui.utils 图书馆。

这是工作: 实例

在撰写本文时,还没有任何使用此指令的示例,因此我做了一个非常 简单的例子 展示这个东西在实践中是如何运作的。

这是简单的方式。作为基本的,我从 http://codepen.io/rpdasilva/pen/dpbff 完成了一些变化。因为现在代码更简单。 你可以得到:在控制器 - “ 4124561232 ”,视图“(412)456-1232

过滤器:

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
.

和指令:

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
.

Try using phoneformat.js (http://www.phoneformat.com/), you can not only format phone number based on user locales (en-US, ja-JP, fr-FR, de-DE etc) but it also validates the phone number. Its very robust library based on googles libphonenumber project.

You can use ng-pattern which is more easy and more light. http://tutorialzine.com/2014/12/learn-regular-expressions-in-20-minutes/. Here u can know about it,,,just some meaningful words,,,not needs any directive or filter,,,,

I took aberke's solution and modified it to suit my taste.

  • It produces a single input element
  • It optionally accepts extensions
  • For US numbers it skips the leading country code
  • Standard naming conventions
  • Uses class from using code; doesn't make up a class
  • Allows use of any other attributes allowed on an input element

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

I modified the code to output phone in this format Value: +38 (095) 411-22-23 Here you can check it enter link description here

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

    };
});

You will need to create custom form controls (as directives) for the phone number and the credit card. See section "Implementing custom form control (using ngModel)" on the forms page.

As Narretz already mentioned, Angular-ui's Mask directive should help get you started.

Simple filter something like this (use numeric class on input end filter charchter 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 !!!
});

Here is the way I created ssn directive which checks for the the pattern and I have used 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);    
            };
        }
    };
}

I solved this problem with a custom Angular filter as well, but mine takes advantage of regex capturing groups and so the code is really short. I pair it with a separate stripNonNumeric filter to sanitize the input:

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

The phoneFormat filter properly formats a phone number with or without the area code. (I did not need international number support.)

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 them simply:

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

The regex for the stripNonNumeric filter came from here.

Find Plunker for Formatting Credit Card Numbers using angularjs directive. Format Card Numbers 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";
  }]);

Inject 'xeditable' module in your angular app(freely available):

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

And then use its built in feature in your HTML code as follows:

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top