Sunday, March 4, 2018

angularJS how to calculation for ng-repeat data shown in input element

Leave a Comment

I have JSON data of items=[]; displayed in <tables> (1st table) using ng-repeat. The user then can add this row using the ng-repeat $index to another array itemsPOS=[] by using push() function, this array then is displayed in another <table> (2nd table) using ng-repeat. So of itemsPOS=[] data are displayed in input fields such as item#, itemDescription, price. What am I trying to do after that, I added fields qty, discount and Total That if I try putting values in qty, it will recalculate the Total just like this plunker: http://plnkr.co/edit/R3LON9?p=preview. But on my version, it's in a table.

What I am facing now is if I added two rows for itemsPOS=[], if I edit the 1st-row qty, it calculates the 2nd row Total. **Just like image below **

enter image description here

My Code to put items at itemsPOS=[];

$scope.passItem = function(index) { var itemNu = $scope.itemLoad[index].itemNo; var descrptn = $scope.itemLoad[index].desc; var cashPrice = $scope.itemLoad[index].cash; var qty = 1; var totalSum = cashPrice*qty;  console.log(totalSum) $scope.presyo = cashPrice;  $scope.itemsPOS.push({'code':itemNu, 'name':descrptn, 'price': cashPrice, 'qty': qty, 'dscnt': 0, 'subTotal': totalSum});  console.log($scope.itemsPOS)  $scope.counter = $scope.itemsPOS.length; 

Code for calculation of Total

$scope.changeQty = function(qty) {     $scope.qnty = qty;      if($scope.qnty>0){         $scope.totalAmount = $scope.presyo*$scope.qnty;     }     console.log($scope.totalAmount) } 

UPDATE The 1st table

<tbody> <tr dir-paginate="it in itemLoad|orderBy:sortKey:reverse|filter:search|itemsPerPage:10"> <td><button type="button" class="btn btn-primary btn-sm" title="Add to POS tab"  ng-click="passItem($index)"><i class="fa fa-plus-circle"></i> Add</button></td> <td><a href="#">{{it.itemNo | ifEmpty: 'Item No.'}}</a></td> <td>{{it.desc | ifEmpty: 'Item Name.'}}</td> <td>{{it.Available | ifEmpty: '0'}}</td> <td>{{it.OnOrder | ifEmpty: '0'}}</td> <td>₱{{it.cash|currency:''| ifEmpty: '0.00'}}</td> <td>₱{{it.charge|currency:''| ifEmpty: '0.00'}}</td> <td>₱{{it.str|currency:''| ifEmpty: '0.00.'}}</td> <td>₱{{it.ins|currency:''| ifEmpty: '0.00'}}</td> </tr>  </tbody> 

2nd table

<tbody> <tr ng-repeat="so in itemForPOS|filter:search"> <td><button type="button" class="btn btn-danger btn-sm" title="Add to POS tab"  ng-click="remItem($index)"><i class="fa fa-times-circle-o"></i> remove</button></td> <td>{{so.code | ifEmpty: 'Item No.'}}</td> <td>{{so.name | ifEmpty: 'Item Name.'}}</td> <td><a><input type="text" value="{{so.price|currency:'₱'}}" style="text-align: center; border: 0;width: 100px" ></a></td> <td><a><input type="text" ng-validate="integer" ng-model="qty" ng-change="changeQty(qty)" placeholder="0" style="text-align: center; border: 0;width: 100px"></a></td> <td><a><input type="text" ng-validate="integer" ng-model="dscnt" style="text-align: center; border: 0;width: 100px" placeholder="0"></a></td> <td><b>{{totalAmount|currency:'₱'}}</b></td> </tr>  </tbody> 

7 Answers

Answers 1

Instead of passing the qnty to changeQty function you have to pass the entire row. Just put the indexing variable used in ng-repeat in the argument, so that you can edit any column in that particular row.

For Eg, consider the sample code,

 <div ng-repeat="x in records">     <button ng-click="changeQty(x)">  </div> 

Answers 2

When ng-repeat is used with filter, then a $index is different than what is expected.

In your case, you are using a search filter with ng-repeat. So when the item is filtered from the list/table then $index is also changed according to the new filtered list.

You can use the workaround of ng-hide where row will be hidden but $index will be maintained or you can pass something unique or complete single object to the function instead of $index.

Answers 3

Not sure if I understand your case but here is a JsFiddle trying to ask your question: Working example. I hope this help you.

You can pass the whole collection and the modified item to the onChange function, then find the element by its id and make your action (calculate total). The same is posible just passing the element index.

It is jus an example, you can do this in few ways.

$scope.onChange = function(collection, item){     collection.forEach(function(prod){         if(prod.id === item.id){             prod.total = prod.qty * prod.price;         }    }); } 

Answers 4

You can try like this below code and also check this plunker link for you example working scenario.

Template:

       <tr ng-repeat="so in itemForPOS">           <td><button type="button" class="btn btn-danger btn-sm" title="Add to POS tab"  ng-click="remItem($index)"><i class="fa fa-times-circle-o"></i> remove</button></td>           <td>{{so.code}}</td>           <td>{{so.name}}</td>           <td><a><input type="number" value="{{so.price}}" style="text-align: center; border: 0;width: 100px" ></a></td>           <td><a><input type="number" ng-model="so.qty" ng-change="changeQty(so)" placeholder="0" style="text-align: center; border: 0;width: 100px"></a></td>           <td><a><input type="number" ng-model="so.dscnt" style="text-align: center; border: 0;width: 100px" placeholder="0"></a></td>           <td><a><input type="number" ng-model="so.subTotal" style="text-align: center; border: 0;width: 100px" placeholder="0"></a></td>         </tr>  

Controller:

$scope.changeQty = function(item) {      if(item.qty>0){         item.subTotal = parseInt(item.price*item.qty);     }     getTotal();   };   function getTotal(){     var tot=0;     for (var i = 0; i < $scope.itemForPOS.length; i++) {       tot = tot + $scope.itemForPOS[i].subTotal;     }     $scope.totalAmount= tot;   } 

Answers 5

There are many solutions given by others already, so I'm going to point out your mistakes here.

As you show in the screen shot, you have a total amount for each row, so assigning many total amounts into a single variable $scope.totalAmount is going to create problem. Same to $scope.presyo.

A simple way to fix this issue is to assign all variables into their respective row object, so each row can have their own total amount.

ng-model for each inputs should also be bound to row object as well, so changing quantity 1 row wouldn't update quantity on other rows.

And an improvement, you can pass the whole item instead of index only in the other function.

// instead of $scope.passItem = function(index) {   var itemNu = $scope.itemLoad[index].itemNo;   var descrptn = $scope.itemLoad[index].desc;   var cashPrice = $scope.itemLoad[index].cash;  // do this $scope.passItem = function(item) {   var itemNu = item.itemNo;   var descrptn = item.desc;   var cashPrice = item.cash; 

Answers 6

This can be achieved by changing the signature of the changeQty method

FROM

$scope.changeQty = function(qty) {     $scope.qnty = qty;      if($scope.qnty>0){         $scope.totalAmount = $scope.presyo*$scope.qnty;     }     console.log($scope.totalAmount) } 

TO

/*The new method now works on the item that is edited and not just the quantity. This method will execute after the ng-model for the control is updated. Hence, item.qty will contain the updated quantity.*/ $scope.changeQty = function(item) {     // This step is not necessary     // $scope.qnty = qty;      if(item.qty>0){         item.subTotal = item.price*item.qty;     } else {         // @TODO Write code to remove item from the itemsPOS     }     // Now we can recaculate the total     reCalculateTotal();     // console.log($scope.totalAmount) } function reCalculateTotal() {     $scope.counter = $scope.itemsPOS.length;     $scope.totalAmount = 0;     $scope.itemsPOS.forEach(function(item){         $scope.totalAmount += item.subTotal;     }); } 

Answers 7

you can send 'it' into passItem function

<button type="button" ng-click="passItem(it)"><i class="fa fa-plus-circle"></i> Add</button> 

and in js funcation:

$scope.passItem = function(item) { var itemNu = item.itemNo; var descrptn = item.desc; var cashPrice = item.cash; var qty = 1; var totalSum = cashPrice*qty;  console.log(totalSum) $scope.presyo = cashPrice;  $scope.itemsPOS.push({'code':itemNu, 'name':descrptn, 'price': cashPrice, 'qty': qty, 'dscnt': 0, 'subTotal': totalSum});  console.log($scope.itemsPOS)  $scope.counter = $scope.itemsPOS.length; 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment