Reputation: 9828
I would like to create a directive for an input control that formats a number with X number of decimal places when the input doesnt have focus. When the input does have focus, i would like the number to appear unformatted (no commas).
I am almost there, with the following code. When you click inside the input, the text changes and when you click out (blur event) the text formats again. However, if i change the value in the input, then the events seem to change round, and the blur event does nothing. Then if you click in the input box again, the value formats when it shouldnt, and the blur event unformats, when it should format.
To use the directive you can simply do
<input number-format ng-model="myValue" decimals="numberOfDecimals" />
Here is the directive
App.directive('numberFormat', ['$filter', '$parse', function ($filter, $parse) {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModelController) {
var decimals = $parse(attrs.decimals)(scope);
ngModelController.$parsers.push(function (data) {
//convert data from view format to model format
return $filter('number')(data, decimals); //converted
});
ngModelController.$formatters.push(function (data) {
//convert data from model format to view format
return $filter('number')(data, decimals); //converted
});
element.bind('focus', function () {
element.val(ngModelController.$modelValue);
});
element.bind('blur', function () {
element.val(ngModelController.$viewValue);
});
}
}
}]);
Upvotes: 1
Views: 12036
Reputation: 3664
Discussion in the question comments appeared to have helped the OP.
$parsers
was causing user-specified input values to be stored to the model value as the filter number format. For example, if 123456
was entered, the underlying model value would be set to 123,456
. The point here is that the model value should be storing the raw user input, not the user input after formatting is applied. A simple implementation to parse the user input for $parsers
would be to use parseFloat()
, like so:
ngModelController.$parsers.push(function (data) {
return parseFloat(data);
});
To be safe, this parsing function should be improved to accommodate for bad user input. I've provided a rudimentary example of this in my demonstration Plunker.
On blur, the value in the input field should be set to the filtered version of the model value.
Upvotes: 3