Building on @1st4ck suggestion, i implemented my own directive that uses angular core filters but displays them as if it were a textbox :)
Directive
var module = angular.module('components.number', []);
module.directive('numberInput', function ($timeout, $filter) {
return {
restrict: 'EA',
templateUrl: "common/components/number/number.tpl.html",
scope:{
ngModel: "=",
format: "=",
min: "=",
max: "=",
step: "=",
decimalPlaces: "=decimals"
},
link: function($scope, $elm, $attrs) {
$scope.showNumber = false;
$scope.numberBlurred = function(){
$scope.showNumber = false;
};
$scope.textBlurred = function(){
$scope.showNumber = true;
};
$scope.textFocused = function(){
$scope.showNumber = true;
$timeout(function(){
$elm.find('input[type=number]').focus();
}, 50)
};
$scope.$watch('ngModel', function(){
var formatted;
if($attrs.format === "percent"){
formatted = $filter("number")($scope.ngModel, 0);
if(formatted){
formatted = formatted + "%";
}
} else if($attrs.format === "decimal"){
formatted = $filter("number")($scope.ngModel, $attrs.decimalPlaces || 2);
} else {
formatted = $filter($attrs.format)($scope.ngModel);
}
$scope.formatted = formatted;
}, true);
}
};
});
return module;
Template ( common/components/number/number.tpl.html )
<input type="number"
ng-model="ngModel"
class="form-control"
ng-show="showNumber"
ng-blur="numberBlurred()" />
<input value="{{formatted}}"
class="form-control"
ng-click="textFocused()"
ng-hide="showNumber" />
Usage
<number-input ng-model="myModel" format="currency">
<number-input ng-model="myModel" format="decimal" decimals="5">
<number-input ng-model="myModel" format="number"> // mainly for thousands
The timeout usage to focus is a bit odd but oh well. Does the job!
Whats great about this solution, it shows the user the UI formatted but preserves the raw values for formatting on the client while using angular native filters :)