What I got from your issue are :
- only accept numbers, replace everything else with ''
- keep 2 decimal digits
- filter user's input and reflect/modify the value to the input element as user types
When binding the input value with ng-model
, actually there are two main values behind the scenes internally: $viewValue
and $modelValue
. And a simple relationship between them is like this:
input DOM value -> $viewValue -> $modelValue
The $parsers
only work between $viewValue
and $modelValue
. So the problem is when you insert a new parser
into the $parsers
, the modified value will only affect the $modleValue
as you simply return a new value in the parse function.
$parsers
are :
Array of functions to execute, as a pipeline, whenever the control reads value from the DOM. The functions are called in array order, each passing its return value through to the next. The last return value is forwarded to the $validators collection
more on : https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#$parsers
And the returned value in the parser function WON'T affect the $viewValue
so what you need to do is to also change that value and reflect on the input DOM element.
Code example:
app.directive('format', ['$filter', function ($filter) {
return {
require: 'ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!ctrl) return;
ctrl.$parsers.unshift(function (viewValue) {
var plainNumber = viewValue.replace(/[^\d|\-+]/g, '');
//use angular internal 'number' filter
plainNumber = $filter('number')(plainNumber/100,2);
//update the $viewValue
ctrl.$setViewValue(plainNumber);
//reflect on the DOM element
ctrl.$render();
//return the modified value to next parser
return plainNumber;
});
}
};
}]);
A working plnkr is here: http://plnkr.co/edit/aoBWhJhlJLiEhBm5hRNX?p=preview
At last, the reason why when you type 6th digit and it disappear is:
As you type 6 digits, the browser will convert and format the number you type to this kind of format: '1,234.56' (pay attention to the COMMA ',', the separator may defer on different browsers) , and you will see a warning given by angular in the console :
The specified value "1,234.56" is not a valid number. The value must match to the following regular expression: -?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)?
which is caused by the restriction from the type='number'
on the input element, angular will perform extra internal validation to match the rule defined by angular itself.