Problem in currency mask in input

4

I'm having a coin mask problem with AngularJS.

I found this thread in Stackoverflow in English. The mask works fine by typing in the input and arrives right in the controller , however when I command formatted the controller to the screen does not scroll. >

Here has an example.

  • Excerpt from the directive
    app.directive('format', ['$filter',
        function ($filter) {
            return {
                require: '?ngModel',
                link: function (scope, elem, attrs, ctrl) {
                    if (!ctrl) return;

                    ctrl.$formatters.unshift(function (a) {
                        return $filter(attrs.format)(ctrl.$modelValue)
                    });

                    ctrl.$parsers.unshift(function (viewValue) {
                        elem.priceFormat({
                            prefix: '',
                            centsSeparator: ',',
                            thousandsSeparator: '.'
                        });

                        return elem[0].value;
                    });
                }
            };
        }
    ]);
  • Page code
    <!DOCTYPE html>
    <html ng-app="plunker">

    <head>
      <meta charset="utf-8" />
      <title>AngularJS Plunker</title>
      <script>
        document.write('<base href="' + document.location + '" />');
      </script>
      <link rel="stylesheet" href="style.css" />
      <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.js"></script><scriptdata-require="[email protected]" src="http://code.angularjs.org/1.2.9/angular.js"data-semver="1.2.9"></script>
      <script src="app.js"></script>
    </head>

    <body ng-controller="MainCtrl">

      <div>
        <br/>Original Example 
    <input type="text" ng-model="test" format="number" /> 
    <pre>{{test|json}}</pre><br/>

    Example 1<input type="text" ng-model="test_2" format="number" /> 
    <pre>{{test_2|json}}</pre><br/>

    Example 2<input type="text" ng-model="test_3" format="number" /> 
    <pre>{{test_3|json}}</pre><br/>

      </div>
    </body>

    </html>
    
asked by anonymous 29.01.2014 / 20:43

2 answers

2

I do not know where you got this code, but it's clearly inconsistent. In one function you use the default% of AngularJS%, in the other you use a jQuery plugin for number formatting.

The $filter only runs at the beginning, with the numbers that are already set in $filter , the other runs at each change.

Although I think it's not a good idea to mix jQuery plugins that deal with DOM elements mixed with AngularJS filters, if you use the same function in both cases it works:

app.directive('format', ['$filter',
  function($filter) {
    return {
      require: '?ngModel',
      link: function(scope, elem, attrs, ctrl) {
        if (!ctrl) return;


        ctrl.$formatters.unshift(function(a) {
          elem[0].value = ctrl.$modelValue
          elem.priceFormat({
            prefix: '',
            centsSeparator: ',',
            thousandsSeparator: '.'
          });
          return elem[0].value;
        });

        ctrl.$parsers.unshift(function(viewValue) {
          elem.priceFormat({
            prefix: '',
            centsSeparator: ',',
            thousandsSeparator: '.'
          });
          return elem[0].value;
        });
      }
    };
  }
]);

Plunker .

ISSUE:

Here's a better way to do this thing:

Set a $scope to do the conversion by partially copying the jQuery plugin code:

app.filter('priceformat', function () {
      var is_number = /[0-9]/;
      var prefix = ''
      var suffix = ''
      var centsSeparator = ','
      var thousandsSeparator = '.'
      var limit = false
      var centsLimit = 2
      var clearPrefix = false
      var clearSufix = false
      var allowNegative = false
      var insertPlusSign = false
      if (insertPlusSign) allowNegative = true;

      function to_numbers(str) {
        var formatted = '';
        for (var i = 0; i < (str.length); i++) {
          char_ = str.charAt(i);
          if (formatted.length == 0 && char_ == 0) char_ = false;
          if (char_ && char_.match(is_number)) {
            if (limit) {
              if (formatted.length < limit) formatted = formatted + char_
            } else {
              formatted = formatted + char_
            }
          }
        }
        return formatted
      }

      function fill_with_zeroes(str) {
        while (str.length < (centsLimit + 1)) str = '0' + str;
        return str
      }

      return function (str) {
        var formatted = fill_with_zeroes(to_numbers(str));
        var thousandsFormatted = '';
        var thousandsCount = 0;
        if (centsLimit == 0) {
          centsSeparator = "";
          centsVal = ""
        }
        var centsVal = formatted.substr(formatted.length - centsLimit, centsLimit);
        var integerVal = formatted.substr(0, formatted.length - centsLimit);
        formatted = (centsLimit == 0) ? integerVal : integerVal + centsSeparator + centsVal;
        if (thousandsSeparator || $.trim(thousandsSeparator) != "") {
          for (var j = integerVal.length; j > 0; j--) {
            char_ = integerVal.substr(j - 1, 1);
            thousandsCount++;
            if (thousandsCount % 3 == 0) char_ = thousandsSeparator + char_;
            thousandsFormatted = char_ + thousandsFormatted
          }
          if (thousandsFormatted.substr(0, 1) == thousandsSeparator) thousandsFormatted = thousandsFormatted.substring(1, thousandsFormatted.length);
          formatted = (centsLimit == 0) ? thousandsFormatted : thousandsFormatted + centsSeparator + centsVal
        }
        if (allowNegative && (integerVal != 0 || centsVal != 0)) {
          if (str.indexOf('-') != -1 && str.indexOf('+') < str.indexOf('-')) {
            formatted = '-' + formatted
          } else {
            if (!insertPlusSign) formatted = '' + formatted;
            else formatted = '+' + formatted
          }
        }
        if (prefix) formatted = prefix + formatted;
        if (suffix) formatted = formatted + suffix;
        return formatted
      }
})

(Here's with the direct values in the code, but you can do different ones)

Then use this filter on your filter :

  ctrl.$formatters.unshift(function(a) {
     return $filter('priceformat')(ctrl.$modelValue)
  });
  ctrl.$parsers.unshift(function(viewValue) {
     return $filter('priceformat')(viewValue)
  });

Plunker .

    
31.01.2014 / 14:52
1

Here I created a function to format.

//Função formatação e Mascara de input.
function funSftMask(value, format) {
    /* Aqui verifica se o campo aceita mais de um formato.
    Ex:(99)99999-9999|(99)9999-9999 sepada por pipe(|)  */
    format = format.indexOf("|") !== -1 ? format.split("|") : format;
    /* Varre a lista e verifica o valor passado e aplica a mascara conforme o tamanho da string. */
    if(format instanceof Array){
        for(var i = 0; i < format.length; i++){
            if(format[i].replace(/[^\d]+/g, '').length === value.length){
                format = format[i];
                break;
            }
        }
    }
    /* Caso não indentifique um tamanho padrão seleciona o primeiro  */
    if(format instanceof Array){
        format = format[1];
    }
    value = value.split("");
    format = format.split("");
    var result = "";
    var x = 0;
    for (var i = 0; i < format.length; i++) {
        if (format[i] !== "9") {
            x--;
        }
        if (x >= value.length)
            break;
        result += format[i] === '9' ? value[x] : format[i];
        x++;
    }
    return result;
}

Here the input you will receive the mask

<input type="text" placeholder="Somente numeros" sft-mack="(99)99999-9999|(99)9999-9999" />

Here is the directive that will format the input as you type.

nomedaApp.directive('sftMack', function () {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            var id = '#' + attrs.id;
            elem.add(id).on('keyup', function () {
                var x = funSftMask(elem.val().replace(/[^\d]+/g, ''), attrs.sftMack);
                elem.val(x);
            });
        }
    };
});
    
16.10.2014 / 22:27