0

I have two columns of checkboxes using ng-repeat, one called 'Calc.' and the other called 'Calc. Final'.

I have a button which I would like, when clicked, to match the selections of Calc. in Calc. Final.

Function:

function updateCalcFinal() {
    vm.desktop.comparables.comp.forEach(e => {
        e.calcFinal = e.calc;
        console.log([e.calcFinal, e.calc]);
    });
}

HTML:

<button class="btn btn-sm btn-primary pull-right mt5 mb5" 
        ng-disabled="deskCtrl.loading" 
        ng-click="deskCtrl.updateCalcFinal()">
  <i class="glyphicon glyphicon-ok"></i>
  &nbsp;&nbsp;Igualar Calc.
</button>

The above code is binding in the console.log but is not being updated in the View. Any help would be much appreciated.

Aleksey Solovey
  • 4,153
  • 3
  • 15
  • 34
jamesbcn
  • 307
  • 4
  • 6
  • 20
  • The objects shown in `console.log` are shown at the time of observation, not at the time of logging. If the objects are amenable to serialization (i.e., have no circular references) it's best to use `console.log(JSON.stringify(e.calcFinal))` – Heretic Monkey Jun 18 '18 at 15:41
  • Possible duplicate of [Angular variable not binding to view](https://stackoverflow.com/questions/32919761/angular-variable-not-binding-to-view) – Heretic Monkey Jun 18 '18 at 15:42
  • The suggested duplicate is not appropriate as the function is being called with `ng-click` which is in fact integrated with the AngularJS framework. – georgeawg Jun 20 '18 at 04:36
  • Please show the HTML that includes the `ng-repeat`. There is likely a scoping issue with that. – georgeawg Jun 20 '18 at 04:38

1 Answers1

0

My experience is that when the console is updated but not the view, there is some asynchronous effect that causing the discrepancy. Like the data is updated but angularjs doesn't know that it's updated.

I would suggest looking up $scope.$apply()

suggested reference: When is it safe to use $scope.$apply()?

Here is a working Plunker that demonstrates the difference and the implementation: https://plnkr.co/edit/vdLJUg2LNIcBz5ng1kwr?p=preview

$scope.withApply = function(){
    $scope.name = 'World';
    console.log('button pressed')
    setTimeout(function(){
      console.log('$scope.name changed to async')
      $scope.name = 'async'
      $scope.$apply()                           <------ $scope.$apply()
    },1000)
  }
  $scope.withOutApply = function(){
    $scope.name = 'World';
    console.log('button pressed')
    setTimeout(function(){
      console.log('$scope.name changed to async')
      $scope.name = 'async'
    },1000)

the apply() function gets called at the end of the async callback, I think you are wrapping your async operation which doesn't work.

TobyGWilliams
  • 631
  • 1
  • 5
  • 17
  • I have changed the code to the following: `function updateCalcFinal() { $scope.$apply( vm.desktop.comparables.comp.forEach(e => { e.calcFinal = e.calc; }) ); }` – jamesbcn Jun 18 '18 at 16:27
  • did it work? I think you need to call $scope.$apply() after the async code returns – TobyGWilliams Jun 18 '18 at 22:04
  • No. This is my latest attempt: function updateCalcFinal() { console.log($scope.$$phase); $timeout(function(){ console.log($scope.$$phase); $scope.$apply(function(){ vm.desktop.comparables.comp.forEach(e => { e.calcFinal = e.calc; }) }); console.log($scope.$$phase); }); } The first console.log returns $apply. The second and third return null. I am no longer receiving the error message but my view still fails to update... – jamesbcn Jun 19 '18 at 07:34
  • I'm really not doing a good job of explaining, check my edited post. – TobyGWilliams Jun 19 '18 at 09:36
  • Thank you Toby for the detailed response. Interestingly, when I switched your Plunker from $scope to ControllerAs (like in my own application) I was unable once more to get it to work. This is despite attempts to inject $scope as a service. Could the issue be with ControllerAs?? – jamesbcn Jun 19 '18 at 19:47
  • I've never used ControllerAs before, I've had a go at updating the plunker for controllerAs and seems to work ok. – TobyGWilliams Jun 20 '18 at 10:06