Angular,输入字段,带有货币掩码指令,用于货币格式

时间:2022-08-22 12:11:28

I'm trying to create an input mask for a EU money field using http://jquerypriceformat.com/

我正在尝试使用http://jquerypriceformat.com/为欧盟货币领域创建输入掩码

So far in my directive, the input shows correctly to the user with the mask applied, but I believe there's something wrong, because the POST values are being sent with weird formatting, totally different than what we see in the input field.

到目前为止,在我的指令中,输入正确显示给应用了掩码的用户,但我认为有些错误,因为POST值是以奇怪的格式发送的,与我们在输入字段中看到的完全不同。

I include the priceformat.js

我包括priceformat.js

<script src="js/jquery.price_format.1.8.min.js"></script>

<input type="text" currency-input ng-model...>

And on angular:

角上:

app.directive('currencyInput', function() {
    return {
      require: '?ngModel',
      link: function($scope, element, attrs, controller) {
        element.priceFormat({
            prefix: '',
            centsSeparator: ',',
            thousandsSeparator: '.'
        });
      }
    };
});

My input shows the value with the mask correctly, but on POST data (called by angular) it's a different value, what am I missing?

我的输入正确显示了掩码的值,但在POST数据(由angular调用)时,它是一个不同的值,我错过了什么?

input > 2.200,80 | post > 22,0080

输入> 2.200,80 |发表> 22,0080

Thanks

谢谢

5 个解决方案

#1


31  

From your example I don't see that link returns something.

从你的例子中我看不到链接返回的东西。

I would write directive something like:

我会写一些指令:

.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;
            });
        }
    };
}]);

Demo 1 Fiddle

演示1小提琴

Angular,输入字段,带有货币掩码指令,用于货币格式

If you want on start fire the filter, use $formatters:

如果你想启动过滤器,请使用$ formatters:

Now link is:

现在链接是:

link: function (scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            var format = {
                    prefix: '',
                    centsSeparator: ',',
                    thousandsSeparator: ''
                };

            ctrl.$parsers.unshift(function (value) {
                elem.priceFormat(format);

                return elem[0].value;
            });

            ctrl.$formatters.unshift(function (value) {
                elem[0].value = ctrl.$modelValue * 100 ;
                elem.priceFormat(format);
                return elem[0].value;
            })
        }

Demo 2 Fiddle

演示2小提琴

#2


17  

Push a $parser to the controller, and only update the value when it doesn't match the input using $setViewValue() and $render().

将$解析器推送到控制器,只有在使用$ setViewValue()和$ render()与输入不匹配时才更新该值。

app.directive('currencyInput', function() {
    return {
      require: '?ngModel',
      link: function($scope, element, attrs, controller) {
        return ctrl.$parsers.push(function(inputValue) {

            ...

            if (result != inputValue) {
                controller.$setViewValue(res);
                controller.$render();
            }
        });
      }
    };
});

Here's a fiddle with the logic I used for my currency input directive: Fiddle

这是我用于货币输入指令的逻辑的小提琴:小提琴

#3


3  

Late to the party, but I believe this deserves another answer! I've been using the ng-currency module. It's absolutely fantastic.

晚会,但我相信这值得另一个答案!我一直在使用ng-currency模块。这真是太棒了。

#4


1  

I like Dubilla's approach cause of its simplicity and elegance. I decided to add (with due credits) some features on top of it to make it quite close to real world use case.

我喜欢Dubilla的简洁和优雅的方法。我决定在其上添加一些功能(并给予应有的信誉),使其非常接近现实世界的用例。

I've using it on a github project to create some useful finance directives github.

我在github项目中使用它来创建一些有用的财务指令github。

Notable extra features:

值得注意的额外功能:

  1. It does some rigorous checking of the inputs to give a valid response.
  2. 它会对输入进行一些严格的检查,以提供有效的响应。
  3. It has some keyboard shortcuts to make entering large numbers quicker.
  4. 它有一些键盘快捷键,可以更快地输入大数字。
  5. I show how to integrate it with bootstrap and ngmodel css updates.
  6. 我将展示如何将它与bootstrap和ngmodel css更新集成。
  7. As a bonus I outputed the form's ngmonel as JSON to help people see how the form validation works in real time
  8. 作为奖励,我将表单的ngmonel作为JSON输出,以帮助人们了解表单验证如何实时工作

It also uses a POJO as the ngmodel:

它还使用POJO作为ngmodel:

function Money() {
    this.notional = 0;
    this.maxValue = 99999999999.9;
    this.maxValueString = "99,999,999,999.9";
    this.maxPrecision = 10;
}

you can use it with Bootstrap 3 like so:

你可以像Bootstrap 3一样使用它:

<h1>Currency Formatting directive</h1>

<div class="row">

    <div class="col-md-6">
        <form name="myForm">

            <div class="form-group" ng-class="{'has-error': myForm.notional.$invalid && myForm.notional.$touched}">
                <input type="text" ng-model="myForm.money.notional  " money="money" money-input size="30" required
                       name="notional"
                       class="form-control"
                       placeholder="Enter notional amount"/>

                      <p class="help-block error" ng-show="myForm.notional.$error.required && myForm.notional.$touched">Required</p>



            </div>

            <button ng-disabled="myForm.$invalid" type="submit">SAVE</button>
        </form>
        <h2>Tips</h2>
        <ol>

            <li> Entering 'k' will multiply the amount by one thousand</li>
            <li> Entering 'm' will multiply the amount by one million</li>
            <li> Entering 'b' will multiply the amount by one billion</li>
        </ol>
    </div>
</div>
<p>Form debugger</p>
<pre>
               form = {{ myForm | json }}
    </pre>

#5


0  

Here's a way to handle this without jQuery using only an Angular directive. This example doesn't support decimals. It's easy to modify it to support that though, just change the $filter in the toView() function.

这里有一种方法可以在没有jQuery的情况下使用Angular指令来处理这个问题。此示例不支持小数。尽管如此,只需更改toView()函数中的$ filter即可轻松修改它以支持它。

In my opinion this is a better approach to solve the same problem, as you can avoid loading in jQuery and the currency plugin mentioned by the author. Locale support for Euro should be supported by the use the $locale properties, but I've only tested this for use in USD.

在我看来,这是一个更好的方法来解决同样的问题,因为你可以避免加载jQuery和作者提到的货币插件。使用$ locale属性应支持对Euro的语言环境支持,但我只测试了这个用于USD。

(function() {
  var app = angular.module('currencyMask', []);

  // Controller
  app.controller('ctrl', ['$scope', function($scope) {
    $scope.amount = 100000;
  }]);

  // Directive
  app.directive('inputCurrency', ['$locale', '$filter', function($locale, $filter) {

    // For input validation
    var isValid = function(val) {
      return angular.isNumber(val) && !isNaN(val);
    };

    // Helper for creating RegExp's
    var toRegExp = function(val) {
      var escaped = val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
      return new RegExp(escaped, 'g');
    };

    // Saved to your $scope/model
    var toModel = function(val) {

      // Locale currency support
      var decimal = toRegExp($locale.NUMBER_FORMATS.DECIMAL_SEP);
      var group = toRegExp($locale.NUMBER_FORMATS.GROUP_SEP);
      var currency = toRegExp($locale.NUMBER_FORMATS.CURRENCY_SYM);

      // Strip currency related characters from string
      val = val.replace(decimal, '').replace(group, '').replace(currency, '').trim();

      return parseInt(val, 10);
    };

    // Displayed in the input to users
    var toView = function(val) {
      return $filter('currency')(val, '$', 0);
    };

    // Link to DOM
    var link = function($scope, $element, $attrs, $ngModel) {
      $ngModel.$formatters.push(toView);
      $ngModel.$parsers.push(toModel);
      $ngModel.$validators.currency = isValid;

      $element.on('keyup', function() {
        $ngModel.$viewValue = toView($ngModel.$modelValue);
        $ngModel.$render();
      });
    };

    return {
      restrict: 'A',
      require: 'ngModel',
      link: link
    };
  }]);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>

<div ng-app="currencyMask" ng-controller="ctrl">
	<input input-currency ng-model="amount">
	<p><strong>Amount:</strong> {{ amount }}</p>
</div>

#1


31  

From your example I don't see that link returns something.

从你的例子中我看不到链接返回的东西。

I would write directive something like:

我会写一些指令:

.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;
            });
        }
    };
}]);

Demo 1 Fiddle

演示1小提琴

Angular,输入字段,带有货币掩码指令,用于货币格式

If you want on start fire the filter, use $formatters:

如果你想启动过滤器,请使用$ formatters:

Now link is:

现在链接是:

link: function (scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            var format = {
                    prefix: '',
                    centsSeparator: ',',
                    thousandsSeparator: ''
                };

            ctrl.$parsers.unshift(function (value) {
                elem.priceFormat(format);

                return elem[0].value;
            });

            ctrl.$formatters.unshift(function (value) {
                elem[0].value = ctrl.$modelValue * 100 ;
                elem.priceFormat(format);
                return elem[0].value;
            })
        }

Demo 2 Fiddle

演示2小提琴

#2


17  

Push a $parser to the controller, and only update the value when it doesn't match the input using $setViewValue() and $render().

将$解析器推送到控制器,只有在使用$ setViewValue()和$ render()与输入不匹配时才更新该值。

app.directive('currencyInput', function() {
    return {
      require: '?ngModel',
      link: function($scope, element, attrs, controller) {
        return ctrl.$parsers.push(function(inputValue) {

            ...

            if (result != inputValue) {
                controller.$setViewValue(res);
                controller.$render();
            }
        });
      }
    };
});

Here's a fiddle with the logic I used for my currency input directive: Fiddle

这是我用于货币输入指令的逻辑的小提琴:小提琴

#3


3  

Late to the party, but I believe this deserves another answer! I've been using the ng-currency module. It's absolutely fantastic.

晚会,但我相信这值得另一个答案!我一直在使用ng-currency模块。这真是太棒了。

#4


1  

I like Dubilla's approach cause of its simplicity and elegance. I decided to add (with due credits) some features on top of it to make it quite close to real world use case.

我喜欢Dubilla的简洁和优雅的方法。我决定在其上添加一些功能(并给予应有的信誉),使其非常接近现实世界的用例。

I've using it on a github project to create some useful finance directives github.

我在github项目中使用它来创建一些有用的财务指令github。

Notable extra features:

值得注意的额外功能:

  1. It does some rigorous checking of the inputs to give a valid response.
  2. 它会对输入进行一些严格的检查,以提供有效的响应。
  3. It has some keyboard shortcuts to make entering large numbers quicker.
  4. 它有一些键盘快捷键,可以更快地输入大数字。
  5. I show how to integrate it with bootstrap and ngmodel css updates.
  6. 我将展示如何将它与bootstrap和ngmodel css更新集成。
  7. As a bonus I outputed the form's ngmonel as JSON to help people see how the form validation works in real time
  8. 作为奖励,我将表单的ngmonel作为JSON输出,以帮助人们了解表单验证如何实时工作

It also uses a POJO as the ngmodel:

它还使用POJO作为ngmodel:

function Money() {
    this.notional = 0;
    this.maxValue = 99999999999.9;
    this.maxValueString = "99,999,999,999.9";
    this.maxPrecision = 10;
}

you can use it with Bootstrap 3 like so:

你可以像Bootstrap 3一样使用它:

<h1>Currency Formatting directive</h1>

<div class="row">

    <div class="col-md-6">
        <form name="myForm">

            <div class="form-group" ng-class="{'has-error': myForm.notional.$invalid && myForm.notional.$touched}">
                <input type="text" ng-model="myForm.money.notional  " money="money" money-input size="30" required
                       name="notional"
                       class="form-control"
                       placeholder="Enter notional amount"/>

                      <p class="help-block error" ng-show="myForm.notional.$error.required && myForm.notional.$touched">Required</p>



            </div>

            <button ng-disabled="myForm.$invalid" type="submit">SAVE</button>
        </form>
        <h2>Tips</h2>
        <ol>

            <li> Entering 'k' will multiply the amount by one thousand</li>
            <li> Entering 'm' will multiply the amount by one million</li>
            <li> Entering 'b' will multiply the amount by one billion</li>
        </ol>
    </div>
</div>
<p>Form debugger</p>
<pre>
               form = {{ myForm | json }}
    </pre>

#5


0  

Here's a way to handle this without jQuery using only an Angular directive. This example doesn't support decimals. It's easy to modify it to support that though, just change the $filter in the toView() function.

这里有一种方法可以在没有jQuery的情况下使用Angular指令来处理这个问题。此示例不支持小数。尽管如此,只需更改toView()函数中的$ filter即可轻松修改它以支持它。

In my opinion this is a better approach to solve the same problem, as you can avoid loading in jQuery and the currency plugin mentioned by the author. Locale support for Euro should be supported by the use the $locale properties, but I've only tested this for use in USD.

在我看来,这是一个更好的方法来解决同样的问题,因为你可以避免加载jQuery和作者提到的货币插件。使用$ locale属性应支持对Euro的语言环境支持,但我只测试了这个用于USD。

(function() {
  var app = angular.module('currencyMask', []);

  // Controller
  app.controller('ctrl', ['$scope', function($scope) {
    $scope.amount = 100000;
  }]);

  // Directive
  app.directive('inputCurrency', ['$locale', '$filter', function($locale, $filter) {

    // For input validation
    var isValid = function(val) {
      return angular.isNumber(val) && !isNaN(val);
    };

    // Helper for creating RegExp's
    var toRegExp = function(val) {
      var escaped = val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
      return new RegExp(escaped, 'g');
    };

    // Saved to your $scope/model
    var toModel = function(val) {

      // Locale currency support
      var decimal = toRegExp($locale.NUMBER_FORMATS.DECIMAL_SEP);
      var group = toRegExp($locale.NUMBER_FORMATS.GROUP_SEP);
      var currency = toRegExp($locale.NUMBER_FORMATS.CURRENCY_SYM);

      // Strip currency related characters from string
      val = val.replace(decimal, '').replace(group, '').replace(currency, '').trim();

      return parseInt(val, 10);
    };

    // Displayed in the input to users
    var toView = function(val) {
      return $filter('currency')(val, '$', 0);
    };

    // Link to DOM
    var link = function($scope, $element, $attrs, $ngModel) {
      $ngModel.$formatters.push(toView);
      $ngModel.$parsers.push(toModel);
      $ngModel.$validators.currency = isValid;

      $element.on('keyup', function() {
        $ngModel.$viewValue = toView($ngModel.$modelValue);
        $ngModel.$render();
      });
    };

    return {
      restrict: 'A',
      require: 'ngModel',
      link: link
    };
  }]);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>

<div ng-app="currencyMask" ng-controller="ctrl">
	<input input-currency ng-model="amount">
	<p><strong>Amount:</strong> {{ amount }}</p>
</div>