问题
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.
回答1:
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.
回答2:
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);
};
}
};
})
回答3:
Make sure you're actually returning a valid value from your functions.
What's likely happening is since the parser returns the same value each time, the formatter assumes the formatted output will not have changed either so it skips the call.
来源:https://stackoverflow.com/questions/18940865/angularjs-currency-format-in-input-box-with-ng-model-how-to-get-formatters-to