nightowl
nightowl

Reputation: 120

AngularJS currency/number output without rounding

I am trying to make a currency/number input/output without rounding.

The issue I come across with using currency is two-fold, (1) it rounds the second decimal once a third number has been entered, (2) that it even allows a third number to be entered. If you notice my del() function, it deletes the end of the number, but while the display might be: $27.46. The string could actually be 27.45606020, and backspacing would delete numbers the user can't even see.

At the moment I have some hacky code that doesn't even bother with AngularJS currency or number and uses a filter to prevent digits after two decimal places, as well when a decimal is added, I have it so it can only be added once.

{{checkTotal | dropDigits}

.filter('dropDigits', function() {
    return function(floatNum) {
        return String(floatNum)
            .split('.')
            .map(function (d, i) { return i ? d.substr(0, 2) : d; })
            .join('.');
    };
})

.

.controller('tipController', function($scope) {

  // Numpad
  $scope.checkTotal = '0.00';

  $scope.clicked = function (label) {
    if($scope.checkTotal === '0.00') {
      $scope.checkTotal = label;
    } else {
      $scope.checkTotal += label;
    }
   };

   // Prevent multiple decimals
   $scope.clickedDot = function() {
      if (($scope.checkTotal.indexOf('.') < 0) || ($scope.checkTotal === '0.00')) {
        if (($scope.checkTotal === '0.00') || ($scope.checkTotal === '')) {
          $scope.checkTotal = '0.';
        } else {
          $scope.checkTotal += '.';
        }
      }
  };

   $scope.del = function () {
      $scope.checkTotal = $scope.checkTotal.slice(0, -1);
   };

});

Upvotes: 0

Views: 2011

Answers (2)

nightowl
nightowl

Reputation: 120

I was able to fix my issue with another if statement

$scope.clicked = function(label) {
  if ($scope.checkTotal === '0.00') {
    $scope.checkTotal = label;
  } else {
    if (($scope.checkTotal.indexOf('.') != -1) && ($scope.checkTotal.substring($scope.checkTotal.indexOf('.')).length > 2)) { //if there is a decimal point, and there are more than two digits after the decimal point
      label.preventDefault();
    } else {
      $scope.checkTotal += label;
    }
  }
};

Upvotes: 0

AWolf
AWolf

Reputation: 8980

You could use Math.floor to cut the decimal places with-out rounding. Just multiply the value inside floor by 100 and do the required math inside and then afterwards divide by 100 to have the correct result size.

Please have a look at the demo below or this fiddle.

angular.module('demoApp', [])
	.controller('mainController', MainController);
    
function MainController($timeout) {
	var vm = this;
    
    angular.extend(vm, {
    	input: 10.25,
        total: 0,
        calcTip: function() {
        	// 10% tip // 2 decimal places no rounding.
            // floor calc. from this SO answer
            // http://stackoverflow.com/questions/4187146/display-two-decimal-places-no-rounding
            vm.total = Math.floor(vm.input * 1.1 * 100) / 100;
        }
    });
    
    vm.calcTip(); // initial calc.
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainController as mainCtrl">
    <input ng-model="mainCtrl.input" ng-change="mainCtrl.calcTip()"/>
    <br/>
    <strong>{{mainCtrl.total | currency}}</strong>
</div>

Upvotes: 1

Related Questions