Angular phone number directive using intl-tel-input lib

18,832

Solution 1

You are right that the model does not get updated automatically. You could make a directive like this

app.directive('intlTel', function(){
  return{
    replace:true,
    restrict: 'E',
    require: 'ngModel',
    template: '<input type="text" placeholder="e.g. +1 702 123 4567">',
    link: function(scope,element,attrs,ngModel){
      var read = function() {
        var inputValue = element.val();
        ngModel.$setViewValue(inputValue);
      }      
      element.intlTelInput({
        defaultCountry:'fr',
      });
      element.on('focus blur keyup change', function() {
          scope.$apply(read);
      });
      read();
    }
  }
});

that could be called like this

<intl-tel ng-model="model.telnr"></intl-tel>

Here is a Plunker

Solution 2

There is a new directive called international-phone-number @ https://github.com/mareczek/international-phone-number

Please checkout, any contributions are welcome

Solution 3

A few of us used Marks's directive, but the lack of testing and jquery's required position in the head was causing issues so ng-intl-tel-input was created:

https://github.com/hodgepodgers/ng-intl-tel-input

Check it out, it's unit and functionally tested with protractor Play with it here:

http://hodgepodgers.github.io/ng-intl-tel-input/

Solution 4

Mark's directive worked for me: https://github.com/mareczek/international-phone-number

One issue with intl-tel-input (at least with v3.6) is that it doesn't format the phone number you initialize it with properly* unless you have a plus sign ('+') before it. This leads to funky behavior for my users. I store my phone numbers normalized (without the plus sign) in my database so I need a hack to get around this. Instead of formatting on the server, I opted to format the phone number on the front-end. I added the following to Mark's directive to get the behavior I needed:

var makeSureInitialValueStartsWithPlusSign = function() {
  var clear_watcher = scope.$watch(attrs.ngModel, function(changes) {
    elem_val = element.val();
    if (elem_val && elem_val[0] != "+") {
      element.val("+" + changes);
      clear_watcher();
    }
  });
};
makeSureInitialValueStartsWithPlusSign();

Thanks Mark

*By properly I mean converting '19734566789' to '+1 973-456-6789'. int-tel-input converts '19734566789' to '1 973-456-6789' (without the pus). When a user goes to edit it, they experience whacky behavior because the plus is not there.

Share:
18,832
lightalex
Author by

lightalex

Updated on June 17, 2022

Comments

  • lightalex
    lightalex almost 2 years

    I am currently trying to create a custom directive that would initialize an input with the following lib : intl-tel-input .

    So I downloaded the required .js file with bower:

    <script src="bower_components/intl-tel-input/build/js/intlTelInput.min.js"></script>
    

    Then I create my input :

    input type="tel" class="form-control" id="tel" name="tel" ng-model="informations.tel" ng-keyup="checkPhoneFormat()" ng-click="checkPhoneFormat()">
    

    And I'm initializing it at the beginning of my controller like this :

    angular.element('#tel).intlTelInput({
        validationScript: "../../bower_components/intl-tel-input/lib/libphonenumber/build/isValidNumber.js",
        preferredCountries: ['en', 'fr']
    });
    

    My problem is that when I'm trying to access the informations.telmodel, it is always undefined. It seems that the input do not update the model value on the fly.

    So I have to write something like this to bind the actual value of my input field with my non updated model value :

        $scope.checkPhoneFormat = function(){
            $scope.informations.telephone = angular.element('#telephone').val();
            ...}
    

    It could be ok but I would like to create a custom directive to initialize such inputs, something like :

    app.directive('phoneInput', function (PhoneFactory) {
        return {
            require: 'ngModel',
            restrict: 'A',
            scope: {
                phoneNumber: '='
            },
            link: function (scope, element, attrs, ctrl) {
                element.intlTelInput({
                     validationScript: "../../bower_components/intl-tel-input/lib/libphonenumber/build/isValidNumber.js",
                     preferredCountries: ['en', 'fr']
                });
    
                ctrl.$parsers.unshift(function(viewValue) {
                    console.log(viewValue);
                });
            }
        };
    });
    

    But as ngModel is undefined the initialization function is never reached... Do you have any idea how I could solve my problem?

  • lightalex
    lightalex almost 10 years
    It is working pretty well :), and do you have any idea how I could return to the view the validity of the input in order to set an error such as : <p class="help-block error" ng-show="registerForm.tel.$error.invalidPhoneFormat && model.telnr">Enter a valid tel number</p>
  • Edminsson
    Edminsson almost 10 years
    Since you already have required the ngModelController in your directive you can just call the $setValidity method. You can read here how it can be used: docs.angularjs.org/api/ng/type/ngModel.NgModelController
  • Sergei Panfilov
    Sergei Panfilov over 8 years
    This directive is require jQuery too, isn't' it?
  • John Lozano
    John Lozano over 8 years
    True, jquery is still required. This addressed the issue of having to place jquery in <head>
  • Abhijeet
    Abhijeet over 8 years
    How to get only Country code (Dial Code) of selected filed ?
  • Abhijeet
    Abhijeet over 8 years
    How to get only Country code (Dial Code) of selected filed ?