My project has a requirement to show amount field in currency format. I can achieve this onblur
event, but let me know if this can be achieved using filters or some other AngularJS technique.
I have the following textbox:
<input type="text" class="form-control" id="MyAmount" name="MyAmount" ng-model="MyAmount" />
I want to convert the value inside this text box to follow currency format. So, if I type 200000, it should make is $200,000.00 as soon as I type or while I am typing.
I used the following technique and applied a filter,
<input type="text" class="form-control" id="MyAmount" name="MyAmount" ng-model="MyAmount"
value="{{MyAmount | currency}}" />
but it only converts for the first key I type, like it converts 2 to $2.00 and then it clears the value (as I guess it finds this updated value as not a number?)
Update: I am able to format it live using a custom filter, but that filter is not working properly in all the cases and when I save the value, I am getting values with $ and commas in the amount and not just the numeric value. I will try more.
It is a rather non-trivial problem.
For the main part of the functionality, you need to use ngModelController
's $formatters
and $parsers
properties to register listeners to handle the changes in $modelValue
and $viewValue
respectively.
When the $modelValue
changes, you need to filter it using the currency
filter before displaying it to the view.
When the $viewValue
changes, you need to convert it to a number (I thought it makes more sense to store the model value as number, not as a formatted string), filter that number through the currency
filter and update the $viewValue
(if necessary).
That is not particularly difficult. The tricky part is that updating the element's value, moves the cursor at the end, so you need to manually re-position the caret.
My attempt resulted in the following Directive Definition Object
{
restrict: 'A',
require: 'ngModel',
link: function postLink(scope, elem, attrs, modelCtrl) {
modelCtrl.$formatters.push(filterFunc);
modelCtrl.$parsers.push(function (newViewValue) {
var newModelValue = toNumber(newViewValue);
modelCtrl.$viewValue = filterFunc(newModelValue);
var pos = getCaretPosition(elem[0]);
elem.val(modelCtrl.$viewValue);
var newPos = pos + modelCtrl.$viewValue.length -
newViewValue.length;
setCaretPosition(elem[0], newPos);
return newModelValue;
});
}
};
See, also, this short demo. It's not perfect, but it's a good start.
BTW, I "borrowed" the get/setCaretPosition()
functions from AngularUI's uiMask
directive.
You can also use the fcsa-number directive that provides this for you automatically. It's as easy as adding the fcsa-number
attribute to the input element.
<input type="text" fcsa-number />
And here is a demo
The source code and documentation is available on GitHub: https://github.com/FCSAmericaDev/angular-fcsa-number
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With