0

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);
   };

});
nightowl
  • 120
  • 2
  • 12

2 Answers2

1

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>
AWolf
  • 8,770
  • 5
  • 33
  • 39
  • If a user only puts in say "5" or $.05, in your example it reads out $.50? – nightowl May 31 '16 at 21:29
  • Nvm..I edited the fiddle [here](https://jsfiddle.net/gk81xc50/) to fix it. I think this solves my problem, the only thing I'm trying to figure out now, is how to convert this into my controller? You have ng-change on an input, but I have buttons that add their 'label' to
    {{checkTotal}}
    from $scope.clicked?
    – nightowl May 31 '16 at 21:36
  • I've updated my answer. It was just the relative calculation. Now it's the total value (tip + input value). – AWolf May 31 '16 at 21:45
  • Just add `ng-click="clicked()"` to your button and it should work. I would recommend to use a better name for your click-handler. So it's easier to read e.g. calcTip. – AWolf May 31 '16 at 21:48
  • clicked() just handles adding numbers to the display, its not actually calculating a tip. The calculated tip updates automatically via another controller. Also, when I add this function, my display reads blank. – nightowl May 31 '16 at 21:58
  • what do you want to do with the `clicked()` method? Do you want it to be like numeric keys that will enter values into the text input after clicking? – AWolf May 31 '16 at 22:06
0

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;
    }
  }
};
nightowl
  • 120
  • 2
  • 12