Reputation: 58662
Please find the fiddle http://jsfiddle.net/q2SgJ/5/
<div ng-app="">
<div ng-controller="Ctrl">
WANTS: {{val | number:2}} in "input" elelent<br>
2 decimal in input: <input ng-model='val'> <br>
2 decimal in input: <input type="number" step="0.01" ng-model='val'><br>
2 decimal in input: <input ng-model='val' value="{{val |number:2}}"> <br>
</div>
</div>
How can I restrict the decimal places to 2 digits in an INPUT field. As in the example {{val | number:2}}
works, but not sure how to use it to format the ng-model attached to an field. I could have formatted the data/model itself, but I have few values I like to keep the extra decimal, but only display 2 decimal.
Thanks.
Upvotes: 15
Views: 26477
Reputation: 91
I have extended the Tim's fiddle incase some one is looking for working solution
http://jsfiddle.net/q2SgJ/653/
modified the keypress event to retrieve the original typed value based on the cursor position
ele.bind('keypress',function(e){
var value = $(this).val();
var decimalPointPosition = value.indexOf(".");
if(!((e.charCode === 46) || (e.charCode > 47 && e.charCode <= 57)))
e.preventDefault();
else if (decimalPointPosition >= 0) {
var decimalCount = value.substring(decimalPointPosition + 1).length;
if ((decimalCount == 2 && $(this).prop("selectionStart") > decimalPointPosition)) {
e.preventDefault();
}
}
}
Upvotes: 0
Reputation: 3390
You can do this without JQuery, and without a directive. Your original attempt with step was very close. I found this site that shows how to use HTML5 inputs to restrict using the step and AngularJS regular expression input filters.
<div ng-app="app">
<div ng-controller="Ctrl"> @*Just an empty controller in this example*@
<form name="myForm">
<input type="number" name="myDecimal" placeholder="Decimal" ng-model="myDecimal" ng-pattern="/^[0-9]+(\.[0-9]{1,2})?$/" step="0.01" /><br />
Is a valid decimal?<span ng-show="!myForm.myDecimal.$valid">{{myForm.myDecimal.$valid}}</span>
</form>
</div>
</div>
Upvotes: 8
Reputation: 497
I expanded on the accepted answer to look at the step attribute when determining how many decimal places to limit.
directive('forcePrecision', function () {
return {
restrict: 'A',
scope: {
step: '@'
},
link: function (scope, element, attrs) {
if (!scope.step || scope.step == 'any') {
return;
}
var prec = 1;
for (var i = scope.step; i != 1; i *= 10) {
prec *= 10;
}
element.on('keypress', function (e) {
var val = Number(element.val() + (e.charCode !== 0 ? String.fromCharCode(e.charCode) : ''));
if (val) {
var newVal = Math.floor(val * prec) / prec;
if (val != newVal) {
e.preventDefault();
}
}
});
}
};
});
Upvotes: 4
Reputation: 12059
You can write a directive to control this functionality. It is not something that ships with angular, but directives can control how things look and work on the page.
I wrote a simple one: http://jsfiddle.net/q2SgJ/8/
This is the linking function that does the trick:
link:function(scope,ele,attrs){
ele.bind('keypress',function(e){
var newVal=$(this).val()+(e.charCode!==0?String.fromCharCode(e.charCode):'');
if($(this).val().search(/(.*)\.[0-9][0-9]/)===0 && newVal.length>$(this).val().length){
e.preventDefault();
}
});
}
This works at limiting the input to 2 decimal places, but doesn't format the input to two decimal places. Anyways, it is a starting point. I am sure you can look up other examples and write your own directive to handle this the way you want. The thing about Angular is that it is not a framework with an answer to every question, but a framework that allows you to create additional functionality than what HTML5 provides alone and makes it very simple.
Upvotes: 8