angularjsdirective

How to create a custom phone number directive using intl-tel-input lib


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.tel model, 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 okay, 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.

How could I solve this problem?


Solution

  • 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