I have searched everywhere for this. Every stack overflow that has an answer, it does not actually work. Same with any examples or google group examples from for angular including the docs.
Seems simple. I want a function to get called on an input for each key pressed by the user.
simple input with a ng-model
<input class="form-control" ng-model="model.thisisnotfun" formatter type="text" required>
According to everything i read. $formatters should update the value from the model to the view calling any functions in the $formatters array. They never get called when i type in the input box.
.directive('formatter', function ($filter, $parse) {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
ngModel.$formatters.push(
function (value) {
console.log('this only gets called on page load');
}
);
}
};
})
I know there are plenty of custom ways to do this, which i have already done. I do not need a work around, i just want to know how to use $formatters correctly to "format" the view data.
very very simple jsfiddle http://jsfiddle.net/fh7sB/4/
Thanks for any help.
I could not get the $formatters function to work like i wanted. I also could not find a single example of what i was looking for anywhere so i am going to post my answer in case someone needs it.
This is a directive for formatting us currency in input boxes with ng-model
.directive('uiCurrency', function ($filter, $parse) {
return {
require: 'ngModel',
restrict: 'A',
link: function (scope, element, attrs, ngModel) {
function parse(viewValue, noRender) {
if (!viewValue)
return viewValue;
// strips all non digits leaving periods.
var clean = viewValue.toString().replace(/[^0-9.]+/g, '').replace(/\.{2,}/, '.');
// case for users entering multiple periods throughout the number
var dotSplit = clean.split('.');
if (dotSplit.length > 2) {
clean = dotSplit[0] + '.' + dotSplit[1].slice(0, 2);
} else if (dotSplit.length == 2) {
clean = dotSplit[0] + '.' + dotSplit[1].slice(0, 2);
}
if (!noRender)
ngModel.$render();
return clean;
}
ngModel.$parsers.unshift(parse);
ngModel.$render = function() {
console.log('viewValue', ngModel.$viewValue);
console.log('modelValue', ngModel.$modelValue);
var clean = parse(ngModel.$viewValue, true);
if (!clean)
return;
var currencyValue,
dotSplit = clean.split('.');
// todo: refactor, this is ugly
if (clean[clean.length-1] === '.') {
currencyValue = '$' + $filter('number')(parseFloat(clean)) + '.';
} else if (clean.indexOf('.') != -1 && dotSplit[dotSplit.length - 1].length == 1) {
currencyValue = '$' + $filter('number')(parseFloat(clean), 1);
} else if (clean.indexOf('.') != -1 && dotSplit[dotSplit.length - 1].length == 1) {
currencyValue = '$' + $filter('number')(parseFloat(clean), 2);
} else {
currencyValue = '$' + $filter('number')(parseFloat(clean));
}
element.val(currencyValue);
};
}
};
})
The $formatters
get called when the model is updated in order to format the value to be presented to the user. The $parsers
do the opposite, i.e. translate the value from a view string to a real model, e.g. a number.
In the forked fiddle here: http://jsfiddle.net/9tuCz/ press the button; it changes the model and fires the $formatters
again.
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