1

I have an array of data that show in a table, that table is editable, and want the fields are dependent on each other.

How I can do that by changing the percentage of a cell, change the amount for that row and vice versa, when you change the amount, also change the percentage? always verifying not exceeding 100% of the sum of the percentages, and the sum of the amounts not exceeding the total amount.

angular .module("app", []) .controller("appController", function ($scope) { $scope.Data = [ { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 } ]; $scope.TotalAmount = 4000.0; });
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <link rel="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" /> </head> <body ng-app="app"> <div class="container" ng-controller="appController"> Total amount: {{TotalAmount}} <table class="table table-striped"> <tr><th>Percent</th><th>Value</th></tr> <tr ng-repeat="invoice in Data"> <td><input type="number" ng-model="invoice.Percent" /></td> <td><input type="number" ng-model="invoice.Value" /></td> </tr> </table> </div> </body> </html>

1
  • Basically its weirdo! but you can add ng-change event on input box, based on total value or % update other row value & %. As you need to do some calculation for other row based on whichever row you making changes. Update other row with equal value like((total value- change row)/(total number of rows-1)) Or you can make the random number generation and make sure its validate with total value and %, it will have lots of permutations & combinations so better use above metioned case. Commented Sep 29, 2016 at 6:10

5 Answers 5

3

You can use ng-change for each input(just like @Pravin Erande said in comments).

I have made a SAMPLE FIDDLE for you(without any calculations)

<tr ng-repeat="invoice in Data"> <td><input type="number" ng-model="invoice.Percent" ng-change="valueChanged($index,invoice.Percent,invoice.Value)" /></td> <td><input type="number" ng-model="invoice.Value" ng-change="valueChanged($index,invoice.Percent,invoice.Value)" /></td> </tr> $scope.valueChanged= function(index,precent,value) { console.log("Index changed "+index+" percent "+precent+" value "+value); $scope.Data[index].Percent = 50; // Assign after calculation $scope.Data[index].Value = 2000; // Assign after calculation } 

You can create a function and pass the $index to that function and update the $scope.Data accordingly after calculation

Sign up to request clarification or add additional context in comments.

Comments

0

Add ng-change event on bothinput box

angular .module("app", []) .controller("appController", function ($scope) { $scope.Data = [ { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 } ]; $scope.TotalAmount = 4000.0; $scope.percentChange=function(index,percent){ var remainpercent=(100-percent)/($scope.Data.length-1); var changerowvalue =$scope.TotalAmount*(percent/100); $scope.Data[index].Value=changerowvalue; var remainValue=($scope.TotalAmount-changerowvalue)/($scope.Data.length-1); for(var i=0;i<$scope.Data.length;i++){ if(i!==index){ $scope.Data[i].Percent=remainpercent; $scope.Data[i].Value=remainValue; } } }; $scope.valueChange=function(index,value){ $scope.Data[index].Percent=(value*100/$scope.TotalAmount); var remainValue=($scope.TotalAmount-value)/($scope.Data.length-1); var remainpercent=(100-$scope.Data[index].Percent)/($scope.Data.length-1); for(var i=0;i<$scope.Data.length;i++){ if(i!==index){ $scope.Data[i].Percent=remainpercent; $scope.Data[i].Value=remainpercent; } } }; });
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <link rel="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" type="text/css" /> </head> <body ng-app="app"> <div class="container" ng-controller="appController"> Total amount: {{TotalAmount}} <table class="table table-striped"> <tr><th>Percent</th><th>Value</th></tr> <tr ng-repeat="invoice in Data"> <td><input type="number" ng-change="percentChange($index,invoice.Percent)" ng-model="invoice.Percent" /></td> <td><input type="number" ng-change="valueChange($index,invoice.Percent)" ng-model="invoice.Value" /></td> </tr> </table> </div> </body> </html>

I haven't added negative cases like posting value greater than total value or for % more than 100

Comments

0

You can achieve it by calling a single function based on the flag.

See the working example.

 angular .module("app", []) .controller("appController", function ($scope) { $scope.Data = [ { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 } ]; $scope.TotalAmount = 4000.0; $scope.changeCalled = function(invoice, flag, index){ var per=0; var value=0; if(flag == 'per') { value = ($scope.TotalAmount * invoice.Percent)/100; $scope.Data[index].Value = value; } else if(flag == 'val') { per = (invoice.Value * 100) / $scope.TotalAmount; $scope.Data[index].Percent = per; } $scope.updateResult(index); } $scope.updateResult = function(index, flag){ var remainedPer = 0; var remainedVal = 0; remainedPer = (100 - $scope.Data[index].Percent)/ ($scope.Data.length - 1); remainedInput = ($scope.TotalAmount - $scope.Data[index].Value)/ ($scope.Data.length - 1); for(i=0; i<$scope.Data.length; i++) { if(i != index) { $scope.Data[i].Percent = remainedPer; $scope.Data[i].Value = remainedInput; } } }; });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <body ng-app="app"> <div class="container" ng-controller="appController"> Total amount: {{TotalAmount}} <table class="table table-striped"> <tr><th>Percent</th><th>Value</th></tr> <tr ng-repeat="invoice in Data"> <td><input type="number" ng-model="invoice.Percent" ng-change="changeCalled(invoice, 'per', $index)"/></td> <td><input type="number" ng-model="invoice.Value" ng-change="changeCalled(invoice, 'val' ,$index)" /></td> </tr> </table> </div> </body>

Comments

0

Thank you all! I took a bit of everyone's comments, but I think it helped me with my problem was ng-change.

I leave an example of what I needed to do.

Regards!

angular .module("app", []) .controller("appController", function ($scope, $filter) { $scope.Data = [ { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 }, { Percent: 25.0, Value: 1000.0 } ]; $scope.TotalAmount = 4000.0; $scope.ValueChanged = function (invoice) { invoice.Value = (invoice.Value == null || invoice.Value.toString() == ".") ? 0 : invoice.Value; invoice.Percent = (invoice.Value * 100.0) / $scope.TotalAmount; CalculateTotals(); ValidateValues(); } $scope.PercentChanged = function (invoice) { invoice.Percent = (invoice.Percent == null || invoice.Percent.toString() == ".") ? 0 : invoice.Percent; invoice.Value = $scope.TotalAmount * (invoice.Percent / 100.0); CalculateTotals(); ValidateValues(); } function CalculateTotals() { var sumPercent = 0; var sumAmount = 0; angular.forEach($scope.Data, function (item, index) { sumPercent += item.Percent; sumAmount += item.Value; }); $scope.CalculatedPercent = sumPercent; $scope.CalculatedAmount = sumAmount; } function ValidateValues() { IsValidAmount(); IsValidPercent(); } function IsValidPercent() { if ($scope.CalculatedPercent == 100.0) { $scope.IsValidPercent = true; $scope.formInvoices.hdCalculatedPercent.$setValidity('valid', true); } else { $scope.IsValidPercent = false; $scope.formInvoices.hdCalculatedPercent.$setValidity('valid', false); } } function IsValidAmount() { if ($scope.CalculatedAmount == $scope.TotalAmount) { $scope.IsValidAmount = true; $scope.formInvoices.hdCalculatedAmount.$setValidity('valid', true); } else { $scope.IsValidAmount = false; $scope.formInvoices.hdCalculatedAmount.$setValidity('valid', false); } } $scope.CalculatedPercent = 100.0; $scope.CalculatedAmount = $scope.TotalAmount; $scope.IsValidPercent = true; $scope.IsValidAmount = true; })
.invalidValue{ color: red; font-weight: bold; } .validValue{ color: black; } .tableWidth{ width: 500px; }
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> </head> <body ng-app="app"> <div class="container" ng-controller="appController"> <form role="form" name="formInvoices"> <table class="table table-condensed table-bordered tableWidth"> <tr> <td class="col-xs-12"><b>Total amount: </b>{{TotalAmount | currency}}</td> </tr> </table> <table class="table table-striped table-condensed table-bordered tableWidth"> <tr> <th>Percent</th> <th>Amount</th> </tr> <tr ng-repeat="invoice in Data"> <td><input type="number" ng-model="invoice.Percent" ng-change="PercentChanged(invoice)" /> %</td> <td>$ <input type="number" ng-model="invoice.Value" ng-change="ValueChanged(invoice)" /></td> </tr> </table> <table class="table table-striped table-condensed table-bordered tableWidth"> <tr> <td class="col-xs-6" ng-class="{'invalidValue': !IsValidPercent,'validValue': IsValidPercent}">{{CalculatedPercent}} %<input name="hdCalculatedPercent" type="hidden" ng-model="CalculatedPercent" /></td> <td class="col-xs-6" ng-class="{'invalidValue': !IsValidAmount,'validValue': IsValidAmount}">{{CalculatedAmount | currency}}<input name="hdCalculatedAmount" type="hidden" ng-model="CalculatedAmount" /></td> </tr> </table> <input type="submit" ng-disabled="formInvoices.$invalid" value="Save" /> </form> </div> </body> </html>

Comments

0

Below is Logic for your need!.

$scope.Data[index].Percent = value/$scope.TotalAmount * 100; $scope.Data[index].Value = precent/100 * $scope.TotalAmount; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.