0

I'm trying to create a prototype that populates a list of unpaid invoices using ng-repeat. Within this, I am creating an input for each invoice. I want to be able to have a user input $ amounts into these inputs and then display a total of all inputs. Going off of this example: http://jsfiddle.net/d5ug98ke/9/ I cannot get it to work as it does in the fiddle. Here is my code:

<table class="table table-striped header-fixed" id="invoiceTable">
        <thead>
          <tr>
            <th class="first-cell">Select</th>
            <th class="inv-res2">Invoice #</th>
            <th class="inv-res3">Bill Date</th>
            <th class="inv-res4">Amount</th>
            <th class="inv-res5">Amount to Pay</th>
            <th class="inv-res6"></th>
          </tr>
        </thead>
        <tbody>
          <tr ng-if="invoices.length" ng-repeat="item in invoices | filter: {status:'Unpaid'}">
            <td class="first-cell"><input type="checkbox" /></td>
            <td class="inv-res2"><a href="invoices/{{item.invoiceNum}}">{{item.invoiceNum}}</a></td>
            <td class="inv-res3">{{item.creationDate}}</td>
            <td class="inv-res4" ng-init="invoices.total.amount = invoices.total.amount + item.amount">{{item.amount | currency}}</td>
            <td class="inv-res5">$
              <input ng-validate="number" type="number" class="input-mini" ng-model="item.payment" ng-change="getTotal()" min="0" step="0.01"  /></td>
          </tr>
        </tbody>
      </table>
      <table class="table">
        <tbody>
          <tr class="totals-row" >
            <td colspan="3" class="totals-cell"><h4>Account Balance:&nbsp;<span class="status-error">{{invoices.total.amount | currency }}</span></h4></td>
            <td class="inv-res4"><h5>Total to pay:</h5></td>
            <td class="inv-res5">${{total}}</td>
            <td class="inv-res6"></td>
          </tr>
        </tbody>
      </table>

And the Angular:

myBirkman.controller('invoiceList', ['$scope', '$http', function($scope, $http) {
        $http.get('assets/js/lib/angular/invoices.json').success(function(data) {
            $scope.invoices = data;
        });

        $scope.sum = function(list) {
             var total=0;
             angular.forEach(list , function(item){
                total+= parseInt(item.amount);
             });
             return total;
        };



        $scope.total = 0;
        $scope.getTotal = function() {
            $scope.invoices.forEach(function(item){
                $scope.tot += parseInt(item.payment);
            });
        };
    }]);

Any help would be appreciated. I dont necessarily need to use the method in the fiddle if someone has a better idea.

Christian Hill
  • 378
  • 1
  • 3
  • 17

1 Answers1

2

It seems there are two issues. First a simple typo:

$scope.tot += parseInt(item.payment, 10);

should be

$scope.total += parseInt(item.payment, 10);

And you should also reset $scope.total to 0 at the beginning of getTotal().

Edit: The way you did it, you always have to remember to update the total when something changes. Instead, you could let getTotal just return the total and write {{ getTotal() }} in the template. You don't have to trigger getTotal() in via ng-change then. If you don't have a lot of inputs you shouldn't worry about performance here.

lex82
  • 11,173
  • 2
  • 44
  • 69
  • or `$scope.total = $scope.invoices.reduce(function(pv, cv) { return pv + cv; }, 0);` – Aprillion Feb 04 '16 at 21:02
  • @Aprillion, or even `$scope.total = $scope.invoices.reduce((pv, cv) => pv + cv);` ;-) – lex82 Feb 04 '16 at 21:10
  • always use `radix` for `parseInt` ... can get unexpected results otherwise – charlietfl Feb 04 '16 at 21:16
  • @charlietfl Thanks, updated it. Can you give me an example in what reasonable situation it leads to unexpected results? In what environments is 10 not the default setting? – lex82 Feb 04 '16 at 21:35
  • 1
    http://stackoverflow.com/questions/850341/how-do-i-work-around-javascripts-parseint-octal-behavior – charlietfl Feb 04 '16 at 21:39
  • @charlietfl Thanks again, didn't know that! – lex82 Feb 04 '16 at 21:41
  • although I think it's now been remedied...just an old habit to recommend it – charlietfl Feb 04 '16 at 21:41
  • see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_removes_octal_interpretation which says it's no longer an issue – charlietfl Feb 04 '16 at 21:43
  • LOL, thanks lex82! Guess i had been looking at the code too long! – Christian Hill Feb 04 '16 at 21:45
  • @ChristianHill You are welcome! Please accept the answer if it solved your problem (click the tick below the votes). – lex82 Feb 04 '16 at 21:50
  • As an aside, can anyone tell me why the code is not accepting the cents? It seems as if even 15.99 in the input is coming to only 15 in the total. – Christian Hill Feb 04 '16 at 21:52
  • @ChristianHill Might be related to parseINT ;-) – lex82 Feb 04 '16 at 21:53
  • you could use `parseFloat` for float numbers, but then you are counting money, so perhaps better look at http://stackoverflow.com/a/2876619/1176601 – Aprillion Feb 05 '16 at 07:58
  • Thanks Aprillion, I changed it to parseFloat right after I posted my question, and it worked like a charm. Much appreciated, though! – Christian Hill Feb 05 '16 at 14:19