Angular, поле ввода с директивой маски валюты для денег на лету
Я пытаюсь создать маску ввода для денежного поля ЕС, используя http://jquerypriceformat.com/
До сих пор в моей директиве вход правильно показывал пользователю с применением маски, но я считаю, что там что-то не так, потому что значения POST отправляются со странным форматированием, совершенно отличным от того, что мы видим в поле ввода.
Я включаю priceformat.js
<script src="js/jquery.price_format.1.8.min.js"></script>
<input type="text" currency-input ng-model...>
И на angular:
app.directive('currencyInput', function() {
return {
require: '?ngModel',
link: function($scope, element, attrs, controller) {
element.priceFormat({
prefix: '',
centsSeparator: ',',
thousandsSeparator: '.'
});
}
};
});
Мой ввод показывает значение с помощью маски правильно, но по данным POST (называемой angular) это другое значение, что мне не хватает?
input > 2.200,80 | пост > 22 0080
Спасибо
Ответы
Ответ 1
В вашем примере я не вижу, что ссылка возвращает что-то.
Я бы написал директиву что-то вроде:
.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;
});
}
};
}]);
Демо 1 Fiddle
![enter image description here]()
Если вы хотите запустить огонь фильтра, используйте $formatters
:
Теперь link
:
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;
})
}
Демо 2 Fiddle
Ответ 2
Нажмите a $parser
на контроллер и обновите значение только в том случае, если оно не соответствует входу с помощью $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();
}
});
}
};
});
Здесь сценарий с логикой, которую я использовал для моей директивы ввода валюты: Fiddle
Ответ 3
Поздно к партии, но я считаю, что это заслуживает другого ответа! Я использовал модуль ng-currency. Это абсолютно фантастический.
Ответ 4
Мне нравится дублинский подход, вызывающий его простоту и элегантность. Я решил добавить (с соответствующими кредитами) некоторые функции поверх него, чтобы сделать его очень близким к реальному использованию.
Я использую его в проекте github для создания полезных директив финансирования github.
Известные дополнительные функции:
- Он выполняет некоторую строгую проверку входов, чтобы дать правильный ответ.
- У него есть несколько сочетаний клавиш, чтобы быстрее вводить большие числа.
- Я покажу, как интегрировать его с обновлениями bootstrap и ngmodel css.
- В качестве бонуса я вывел форму ngmonel как JSON, чтобы помочь людям увидеть, как валидация формы работает в режиме реального времени.
Он также использует POJO в качестве ngmodel:
function Money() {
this.notional = 0;
this.maxValue = 99999999999.9;
this.maxValueString = "99,999,999,999.9";
this.maxPrecision = 10;
}
вы можете использовать его с 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
Здесь можно обработать это без jQuery, используя только директиву Angular. Этот пример не поддерживает десятичные знаки. Легко изменить его, чтобы поддержать это, но просто измените $filter
в функции toView()
.
По-моему, это лучший подход для решения одной и той же проблемы, так как вы можете избежать загрузки в jQuery и плагин валюты, упомянутый автором. Поддержка локалей для евро должна поддерживаться с помощью свойств $locale
, но я тестировал это только для использования в долларах США.
(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>