1
votes

On the form we have a masked input that works via directive using jquery plugin.

That works about fine — users see masked phone value (but only after focus), BUT we need to have unmaksed model value instead of masked (for instance if we type phone (123)456-78-90 we have to have model as 1234567890 and at the same time we have to see in our field (123)456-78-90).

Ok, lets add ngModel.$parsers to directive. Ok, thats work fine — as we need.

  .directive('phoneNumber', function() {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function($scope, element, attrs, ngModel) {

        $(element).mask('(999) 999-99-99');

        // view -> model
        ngModel.$parsers.push(function(value) {
          if (value) {
            return value.replace(/[^0-9]+/g, '');  
          }
        });

      }
    }
  });

BUT when I add validation rules

  <input type="text" class="form-control" 
    ng-model="phone" name="phone"
    phone-number
    ng-pattern="^\d+$"
    ng-maxlength="10"
    ng-minlength="10"
    placeholder="(999)999-99-99">
  • ng-pattern="^\d+$" I get valid pattern, ok, that works
  • ng-minlength="10" I get valid minlength, ok, that works too
  • ng-maxlength="10" I get validation error because of maxlength. It seems that in that case validation is using (123)456-78-90 value instead of 1234567890.

And my questions are here:

  • How to get masked value with default model value (at the beginning I get 1234567890 instead of (123)456-78-90), I see masked value only after field getting focus
  • How can I get working validation (ng-pattern, ng-min/maxlength) with masked input?

See plnkr with my sample of code http://plnkr.co/edit/Kalv9N2bP27v1ENAfefb?p=preview

1
To get it displayed correctly, call $scope.$apply() just before calling $(element).mask(...) - Martin E. Zulliger

1 Answers

0
votes

ok after playing a bit, I got it to work:

http://plnkr.co/edit/v9dvwaFzwOw4rkwhbMnM?p=preview

Couple things:

  1. I had to do $scope.$apply after doing mask as I said in the comments
  2. Since jQuery's mask messes with the object's value, I had to do a not-so-pretty check for the validator, but it works :).

Code:

 .directive('phoneNumber', function() {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function($scope, element, attrs, ngModel) {

        $scope.$apply();
        $(element).mask('(999) 999-99-99');


        // view -> model
        ngModel.$parsers.push(function(value) {
          if (value) {
            return value.replace(/[^0-9]+/g, '');  
          }
        });

      }
    }
  });

Html:

<input type="text" class="form-control" 
    ng-model="phone" name="phone" phone-number >

<span class="text-danger" 
    ng-show="appForm.phone.$dirty && appForm.phone.$invalid || !phone">
    Incorrect phone value
</span>