-1

I am not using some complex directive, but rather simple multiplication and angular's 2-way binding seems to fail. When I say fail, it's not updating the view when I multiply. But when I click on some UI element or change the view in some way like click a radio button. The value magically appears. After some investigation, I found out that the apply is not being called when I multiply. So I added a $scope.$apply(function(){}). Which seem to fix it. But as I read in some post. You should never try explicitly calling $apply. Which begs the question. What the hell is happening? The console.log() is showing the changed value but the value is not being applied in the view. Also I am not directly manipulating the scope. For ex.

 $scope.calculateOutstationCharges = function() {
        if ($scope.customer.calculatedDistance !== 0) {
            console.log($scope.customer.kmlimit * $scope.carPricing.perKmCharge * $scope.customer.days);
            if (($scope.customer.calculatedDistance * 2) < $scope.carPricing.kmlimit * $scope.customer.days) {
                $scope.customer.totalprice_outstation = $scope.carPricing.kmlimit * $scope.carPricing.perKmCharge * $scope.customer.days + $scope.customer.driverCharge;
//console.log($scope.customer.totalprice_outstation). This value is not updated in the view
            } else {
                $scope.customer.totalprice_outstation = ($scope.customer.calculatedDistance * 2 * $scope.carPricing.perKmCharge)+  $scope.customer.driverCharge;
                //console.log($scope.customer.totalprice_outstation); nor is this one
            }
            $scope.customer.totalprice_outstation += $scope.customer.extra_outstation;
        }
         $scope.customer.driverCharge = $scope.carPricing.driverCost;
$scope.$digest(); //this does it but with $apply in progess error.
    };

Values are updated in the next digest cycle, not in the cycle in which values are being created. If anyone of you has encountered similar what did you do to solve it? Thanks

Saras Arya
  • 3,022
  • 8
  • 41
  • 71
  • How do you call `calculateOutstationCharges`? – Bartosz Gościński Sep 09 '16 at 19:18
  • I was calling it from a function which looked like this `function calcDistance()` The thing about this question was when we say outside of angular we mean functions and variables which are not attached to angular's scope. In this case the calling function was not attached to angular and hence was creating issues. Fixed that now working. – Saras Arya Sep 10 '16 at 08:27

2 Answers2

1

$scope.CalculateOutstationCharges is called from outside of context of angular (am i right on this?).

Angular doesn't know that the $scope variables are changed. You need to explicity tell the angular this. To achieve that, you have to call,

$timeout(function(){$scope.$apply();})

Which would wait for the current digest cycle to complete. Then it will apply changed $scope variables on DOM.

Bharat
  • 162
  • 8
  • Could you explain context of angular? – Saras Arya Sep 10 '16 at 08:29
  • Let's say you are using jQuery function in your angular application that calls an api and assigns a response to a $scope variable. Now, after the API call is made, value is also assigned to a variable (let's say $scope.output). If you are printing {{$scope.output}} in your HTML, you will not see the updated value i.e. response. Reason: jQuery is responsible for changing $scope.output (and it is outside of the context of AngularJS). AngularJS doesn't know that the variable has been changed. I hope this explains something... – Bharat Sep 10 '16 at 09:10
  • @Bharat You don't have to call `$apply` inside `$timeout` callback – Bartosz Gościński Sep 10 '16 at 10:48
  • Actually many times you have to. To allow the current digest cycle to end. Otherwise it will give u error. – Bharat Sep 10 '16 at 10:56
  • Can you provide an example plunker? – Bartosz Gościński Sep 10 '16 at 10:58
  • This would make things clear: http://stackoverflow.com/questions/23070822/angular-scope-apply-vs-timeout-as-a-safe-apply – Bharat Oct 14 '16 at 04:49
0

Events outside the context of angular should inform angular of the change, as you mentioned that $apply is not recommended.

Check $applyAsync([exp]);

Alex Mounir
  • 1,243
  • 1
  • 14
  • 20
  • Can you explain what you mean by the context of angular? As far I am understanding anything that is attached to the angular's scope. Am I correct? Because calling in a controller from a function signature like `function calcDistance()` didn't seem to work. – Saras Arya Sep 10 '16 at 08:29
  • @SarasArya No. If function is called inside angular context or not depends on "who" calls it. For example: functions that you pass to module.{controller, directive, factory, etc.}, directives' link, compile functions, expressions in templates (ng-click), $timeout callbacks... are all called inside angular context. Things that are outside it are: "native" event listeners, setTimeout callbacks, fetch promise handlers,... You can read more about it here: https://www.sitepoint.com/understanding-angulars-apply-digest/. Also note that this issue is resolved in angular 2 using `zone.js`. – Bartosz Gościński Sep 10 '16 at 10:57