I have a input to show a formatted number. Normally, when it has no focus, it should show a formmatted string, e.g. '$50,000.00'. But when it has focus, it should show the raw value, e.g. 50000 for editing.
Is there any built-in functions? Thanks!
Here is a directive (formatOnBlur
) which does what you want.
Note that only the element's display value is formatted (the model-value will always be unformatted).
The idea is that you register listeners for the focus
and blur
events and update the display value based on the focus-state of the element.
app.directive('formatOnBlur', function ($filter, $window) {
var toCurrency = $filter('currency');
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
var rawElem = elem[0];
if (!ctrl || !rawElem.hasOwnProperty('value')) return;
elem.on('focus', updateView.bind(null, true));
elem.on('blur', updateView.bind(null, false));
function updateView(hasFocus) {
if (!ctrl.$modelValue) { return; }
var displayValue = hasFocus ?
ctrl.$modelValue :
toCurrency(ctrl.$modelValue);
rawElem.value = displayValue;
}
updateView(rawElem === $window.document.activeElement);
}
};
});
See, also, this short demo.
You're looking for the ngModel.$parsers and ngModel.$formatters.
I've put together a simple demo:
http://jsfiddle.net/BuriB/nD2tk/
angular.module('app', [])
.controller('TestCntrl', function TestCntrl ($scope) {
$scope.value = 50000;
})
.directive('numberFormatter', ['$filter', function ($filter) {
var decimalCases = 2,
whatToSet = function (str) {
/**
* TODO:
* don't allow any non digits character, except decimal seperator character
*/
return str ? Number(str) : '';
},
whatToShow = function (num) {
return '$' + $filter('number')(num, decimalCases);
};
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attr, ngModel) {
ngModel.$parsers.push(whatToSet);
ngModel.$formatters.push(whatToShow);
element.bind('blur', function() {
element.val(whatToShow(ngModel.$modelValue))
});
element.bind('focus', function () {
element.val(ngModel.$modelValue);
});
}
};
}]);
See, also, this Working Demo by @Eric Hannum.
you can use ng-focus to apply a filter/transformation yo your model to make it the raw value and ng-blur to make it the formatted value as for the formatting part am afraid you'll have to build your own filter. i don't know of any existing one to perform this operation, although maybe there is.
myApp.directive('myField',function($filter){
return {
restrict: 'E',
require: '?ngModel',
scope : true,
template: '<input type="text" ng-focus="clearFormat()" ng-blur="formatField()"/>',
link : function (scope, element, attrs,ctrl){
var field = element.find('input');
ctrl.$render = function() {
field.val($filter('currency')(ctrl.$viewValue));
};
scope.clearFormat = function(){
field.val(ctrl.$viewValue);
}
scope.formatField = function(){
field.val($filter('currency')(ctrl.$viewValue));
}
function updateViewValue() {
scope.$apply(function() {
ctrl.$setViewValue(field.val());
});
}
field.on('change', updateViewValue);
}
};
})
In the html
<my-field ng-model="amount"></my-field>
This will work only if you use angular 1.2 or above. Else you need to implement ng-focus and and ng-blur by your own
angular.module('app', [])
.controller('TestCntrl', function TestCntrl($scope) {
$scope.value = 50000.23;
})
.directive('numberFormatter', ['$filter', function ($filter) {
return {
restrict: 'A',
require: 'ngModel',
scope: { 'decimal': '=decimal' },
link: function (scope, element, attr, ngModel) {
ngModel.$parsers.push(whatToSet);
ngModel.$formatters.push(whatToShow);
element.bind('blur', function () {
element.val(whatToShow(ngModel.$modelValue, scope.decimal))
});
element.bind('focus', function () {
element.val(ngModel.$modelValue);
});
function whatToSet(str) {
var num = 0
var numbe = num !== undefined ? num : 0;
var strr = str.toString();
strr = strr.replace(',', '.');
numbe = parseFloat(strr);
return numbe;
}
function whatToShow(num) {
if (num) {
return '$' + $filter('number')(num, scope.decimal);
} else {
return '';
}
};
}
};
}]);
<!doctype html>
<html lang="en">
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
</head>
<body ng-app="app" ng-controller="TestCntrl">
<input type="text" id="exampleInput" name="input" ng-model="value" number-formatter decimal="'0'" /><br />
<strong>value in the model:</strong> {{value}}
</body>
</html>