37

Have a kind of price range/rating functionality based on an inputs model. On load, when it's set from the backend, it starts off as an integer, but when you type in it, it changes to a string. Is there any way in Angular to declare the value of an input as integer?

HTML:

<input type="text" name="sellPrice" id="sellPrice" class="sell-price" data-ng-model="menu.totalPrice" data-ng-change="updateMenuPriceRange()"required>

JS:

$scope.updateAggregatePricing();

if ($scope.menu.totalPrice === 0) {
    $scope.menuPriceRange = "";
} else if ($scope.menu.totalPrice < 10) {
    $scope.menuPriceRange = "$";
} else if ($scope.menu.totalPrice >= 10 && $scope.menu.totalPrice <= 12.50) {
    $scope.menuPriceRange = "$$";
} else if ($scope.menu.totalPrice >= 12.51 && $scope.menu.totalPrice < 15) {
    $scope.menuPriceRange = "$$$";
} if ($scope.menu.totalPrice >= 15) {
    $scope.menuPriceRange = "$$$$";
} else {
    $scope.menuPriceRange = "";
}
beaudetious
  • 2,354
  • 3
  • 36
  • 60
Christopher Marshall
  • 10,678
  • 10
  • 55
  • 94

4 Answers4

85

I know I'm late but I figured I'd post this answer as other people might still be searching for alternatives.

You could solve this by using the AngularJS directive linking function. The code:

var myMod = angular.module('myModule', []);

myMod.directive('integer', function(){
    return {
        require: 'ngModel',
        link: function(scope, ele, attr, ctrl){
            ctrl.$parsers.unshift(function(viewValue){
                return parseInt(viewValue, 10);
            });
        }
    };
});

You would then use this directive on an input element to make sure that any value you enter, gets parsed to an integer. (obviously this example doesn't validate the input to make sure that what was entered is in fact an integer, but you could easily implement this with the use of regular expressions for example)

<input type="text" ng-model="model.value" integer />

More information about this topic can be found on the AngularJS docs on forms, right around the section of "Custom validation": http://docs.angularjs.org/guide/forms .

Edit: Updated parseInt() call to include the radix 10, as suggested by adam0101

Yanik Ceulemans
  • 1,182
  • 9
  • 17
  • 1
    Thanks! This helped with an issue I was having where I had radio buttons with values bound to the same model as a input (type=number). – Dave May 14 '13 at 10:42
  • Aha! I knew there had to be a less kludgy way to do this than what I've been doing. :) Thanks! – Sasha Chedygov Aug 28 '13 at 05:25
  • Changing this as the answer since it's reusable and seems like the the right way to do it :} Thanks! – Christopher Marshall Apr 02 '14 at 15:59
  • This is AWESOME...if I could upvote it more, I would! – CSharpAtl Jun 23 '14 at 17:17
  • Brilliantly awesome! Has helped to teach me another aspect of AngularJS. Thank you – user115014 Jun 25 '14 at 21:24
  • 4
    You should include a radix of 10 as in parseInt(viewValue, 10) otherwise a leading zero may give an unexpected value in some browser implementations. – adam0101 Jul 14 '14 at 19:47
  • I get this error when I try using this solution: https://docs.angularjs.org/error/$compile/ctreq?p0=ngModel&p1=integer – user1429980 Feb 05 '15 at 18:15
  • As I can't see your code, I'm going to go with the information from the URL you specified. It seems that this error occurs because the specified required controller (in this case 'ng-model') could not be found on the element that has the 'integer' directive on it. In my last code sample above, I specify the minimum amount of attributes needed for this directive to work. When using it, you need to add `integer` and `ng-model` to your element. – Yanik Ceulemans Feb 05 '15 at 22:14
  • can anyone provide a type script version of this directive please? – Souhaieb Besbes Mar 24 '16 at 16:25
  • 1
    The given example pulls NaN to model if the input is empty. Maybe that is desired effect but in most usecases I would expect 0 in the model. The solution is [here](http://stackoverflow.com/a/28351640/267197). – dma_k Feb 14 '17 at 22:53
23

Yes, use input of type number:

<input type="number" name="sellPrice" ...>
pkozlowski.opensource
  • 117,202
  • 60
  • 326
  • 286
8

Ended up parsing the model as an integer before my conditional.

$scope.menu.totalPrice = parseInt($scope.menu.totalPrice, 10);
Christopher Marshall
  • 10,678
  • 10
  • 55
  • 94
0

Very similar to the accepted answer from Yanik, except I tried that and it didn't work. This version from the AngularJS documentation is working perfectly for me, though.

.directive('stringToNumber', function() {
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
          ngModel.$parsers.push(function(value) {
            return '' + value;
          });
          ngModel.$formatters.push(function(value) {
            return parseFloat(value);
          });
        }
      };
    });
claywhipkey
  • 897
  • 8
  • 13