Search code examples
javascriptangularjsangularjs-directiveangularjs-scope

$viewValue is not applying in textbox directive?


Try to create masking
Console Print $viewValue is different but not apply in view.

NgModelController {$viewValue: "656-56", $modelValue: "656565", $$rawModelValue: "656565", $validators: Object, $asyncValidators: Object…}

Code :

var app = angular.module("masking",[]);
app.directive('textbox', function mask() {
      return {
        restrict: 'E',
        transclude: true,
        require: 'ngModel',
        scope: { },
        bindToController: {
            model: "=ngModel",
        },
        controller: function($scope, $attrs) {

        },
        compile: function() {
            return {
                pre: function(scope, el, attrs) {
                },
                post: function(scope, element, attrs, Ctrls) {
                 }
            };
        },
        template: '<div><input type="text" ng-model="Ctrl.model" /> </div> ',
        controllerAs: 'Ctrl',
    };
});

app.directive('angularMask', function () {
    return {
      restrict: 'A',
      require: 'ngModel',
      scope: false,
      link: function ($scope, el, attrs, model) {
        $scope.$watch(function(){return attrs.angularMask;}, function(value) {
          if (model.$viewValue != null){
            model.$viewValue = mask(String(model.$viewValue).replace(/\D/g, ''));
            el.val(model.$viewValue);
          }
        });

        model.$formatters.push(function (value) {
          return value === null ? '' : mask(String(value).replace(/\D/g, ''));
        });

        model.$parsers.push(function (value) {
          model.$viewValue = mask(value);
          var modelValue = attrs.isModelValueEqualViewValues ? model.$viewValue : String(value).replace(/\D/g, '');
          el.val(model.$viewValue);
          return modelValue;
        });

        function mask(val) {
                    console.log(model);

          var format = attrs.angularMask,
          arrFormat = format.split('|');

          if (arrFormat.length > 1) {
            arrFormat.sort(function (a, b) {
              return a.length - b.length;
            });
          }

          if (val === null || val == '') {
            return '';
          }
          var value = String(val).replace(/\D/g, '');
          if (arrFormat.length > 1) {
            for (var a in arrFormat) {
              if (value.replace(/\D/g, '').length <= arrFormat[a].replace(/\D/g, '').length) {
                format = arrFormat[a];
                break;
              }
            }
          }
          var newValue = '';
          for (var nmI = 0, mI = 0; mI < format.length;) {
            if (!value[nmI]) {
              break;
            }
            if (format[mI].match(/\D/)) {
              newValue += format[mI];
            } else {
              newValue += value[nmI];
              nmI++;
            }
            mI++;
          }
          return newValue;
        }
      }
    };
  });

HTML Code

<textbox ng-model="myModelPhone" angular-mask="000-000-000"></textbox>
    {{myModelPhone}}

https://jsfiddle.net/amitme/s0Lenp0w/1/ here is jsfiddle link


Solution

  • Basically you shouldn't be applying angular-mask directive over a same element where you had used textbox directive. Because If you placed it over ngModel of the textbox model not the inner ngModelController.

    You need to change your directive structure little. from textbox directive just pass masking pattern in attribute like masking-pattern="000-000-000"

    and then change the directive template to

    template: function(element, attrs){
       return '<div><input type="text" ng-model="Ctrl.model" angular-mask="'+attrs.maskingPattern+'"/> </div> '
    }
    

    HTML

    Text box directive : <textbox ng-model="myModelPhone" masking-pattern="000-000-000"></textbox>
    {{myModelPhone}}
    

    Demo Fiddle