简体   繁体   中英

AngularJS Issue in ng-repeat data binding

Scenario

I have a repeater using ng-repeat which binds to a array of dynamic/ run time computed values. ( ie, my array contains fields like Brokerage: ($scope.BuyValue() + $scope.SellValue())* 0.5/100 ).

Problem

When i change the value in the input box which has a ng-model , field Broker.Brokerage inside the repeater is not getting refreshed. But i am able to update/bind the fields outside the repeater properly.

Code

<body ng-controller="BrokerController">
<div>
  <div>
    Buy Price   <input type="textbox" ng-model="BuyPrice"/><br/> 
    Sell Price  <input type="textbox" ng-model="SellPrice"/><br/> 
    Quantity    <input type="textbox" ng-model="Quantity"/><br/> 
    Buy Value   {{ BuyValue() }} <br/>
    Sell Value   {{ SellValue() }} <br/>
    Profit   {{ Profit() }} <br/><br/><br/>
    <h4>Brokers</h4>
    <div ng-repeat='Broker in Brokers'>
      Broker Name : <b>{{Broker.BrokerName}}</b>
      Brokerage Amount : <i>{{Broker.Brokerage}}</i>  ({{Broker.BrokerageDetail}})
      <br/>
    </div>
  </div>
</div>
  <script id="angularjs"  src="js/lib/angular/angular.js"></script>
  <script>
  var App = angular.module('ChooseYourBroker', []);

App.controller("BrokerController", ['$scope', function ($scope) {    
$scope.BuyPrice = 10;
$scope.SellPrice = 20;
$scope.Quantity = 100;
$scope.BuyValue = function(){ return ( $scope.BuyPrice * $scope.Quantity )};
$scope.SellValue = function(){ return ( $scope.SellPrice * $scope.Quantity )};
$scope.Profit = function(){ return ( $scope.SellValue() - $scope.BuyValue() )};
$scope.Brokers = [
    {
        BrokerName: 'Broker one', 
        BrokerageDetail :'0.5% value of Sell Value', 
        Brokerage: $scope.SellValue() * 0.5/100
    },
    {
        BrokerName: 'Broker two',  
        BrokerageDetail :'2% value of Sell Value', 
        Brokerage: $scope.SellValue() * 2/100
    },
    {
        BrokerName: 'Broker three', 
        BrokerageDetail :'1% value of Sell Value',  
        Brokerage: $scope.SellValue() * 1/100
    },
    {
        BrokerName: 'Broker Four', 
        BrokerageDetail :'0.5 % value of Buy Value and Sell Value',  
        Brokerage: ($scope.BuyValue() + $scope.SellValue())* 0.5/100
    }];
  }]);



  </script>   

This is because Brokerage is calculated once, when it is run. Since you did not make a getter function of it or did not run a watcher, it will not be updated. You have two options:

Option 1. Make a getter function

JS:

{
    BrokerName: 'Broker Four', 
    BrokerageDetail :'0.5 % value of Buy Value and Sell Value',  
    GetBrokerage: function () { return ($scope.BuyValue() + $scope.SellValue())* 0.5/100;}
} 

HTML:

<span ng-bind="Broker.GetBrokerage()"></span>

Option 2. Watch BuyValue and SellValue , and update Brokers .

JS:

$scope.$watch("BuyValue()", function () { /*update all the brokers*/ });
$scope.$watch("SellValue()", function () { /*update all the brokers*/ });

You need to set a $watch on SellValue() in order to be notified whenever the returned value changes:

$scope.$watch('SellValue()',function(newValue){
    for(var i=0;i<$scope.Brokers.length;i++){
        $scope.Brokers[i].Brokerage = ... * newValue; // Calculate the Brokerage
    }
});

Explanation: The view can bind to model values through the scope. The Brokers object is not a view element and so is not bound to anything. A $watch is needed when the model wants to be notified in changes to other parts of the model. Otherwise, your Brokerage property gets calculated only once during the controller's initial run phase.

Here is a fiddle where I've created a BrokerageRate to compute the new Brokerage any time the SellValue() changes.

Broker Four will need a little more work in that there will need to be another watch on BuyValue() as that Brokerage property needs to be notified of changes to both values.

fiddle

So angularJS ng-model doesn't update primitives. If you want it to automatically update it would be better to do something like

$scope.share={};
$scope.share.BuyPrice = 10;
$scope.share.SellPrice = 20;
$scope.share.Quantity = 100;

and change

Buy Price   <input type="textbox" ng-model="BuyPrice"/><br/> 
Sell Price  <input type="textbox" ng-model="SellPrice"/><br/> 
Quantity    <input type="textbox" ng-model="Quantity"/><br/> 

to

Buy Price   <input type="textbox" ng-model="share.BuyPrice"/><br/> 
Sell Price  <input type="textbox" ng-model="share.SellPrice"/><br/> 
Quantity    <input type="textbox" ng-model="share.Quantity"/><br/> 

That way the values of share will automatically update without needing to use $watch or setters and getters. However it will not automatically call function(){ return ( $scope.SellValue() - $scope.BuyValue() )}; again

To do this I would do

Buy Price   <input type="textbox" ng-model="share.BuyPrice" ng-change="updatePrices()"/><br/> 
Sell Price  <input type="textbox" ng-model="share.SellPrice" ng-change="updatePrices()"/><br/> 
Quantity    <input type="textbox" ng-model="share.Quantity" ng-change="updatePrices()"/><br/> 

and

$scope.updatePrices=function(){
  $scope.share.BuyValue = function(){ return ( $scope.share.BuyPrice * $scope.share.Quantity )};
  $scope.share.SellValue = function(){ return ( $scope.share.SellPrice * $scope.share.Quantity )};
  $scope.share.Profit = function(){ return ( $scope.share.SellValue() - $scope.share.BuyValue() )};
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM