dman
dman

Reputation: 11073

Angular.js - Digest is not including $scope member changes

I have a service that includes:

  newStatusEvent = function(account, eventId, url, deferred, iteration) {
    var checkIteration;
    checkIteration = function(data) {
      if (iteration < CHECK_ITERATIONS && data.Automation.Status !== 'FAILED') {
        iteration++;
        $timeout((function() {
          return newStatusEvent(account, eventId, url, deferred, iteration);
        }), TIME_ITERATION);
      } else {
        deferred.reject('failure');
      }
    };

    url.get().then(function(data) {
      if (data.Automation.Status !== 'COMPLETED') {
        checkIteration(data);
      } else {
        deferred.resolve('complete');
      }
    });
     return deferred.promise;
  };

  runEventCheck = function(account, eventId, modalInstance, state) {
    newStatusEvent(account, eventId, urlBuilder(account, eventId), 
        $q.defer(), 0)
      .then(function() {
           scopeMutateSuccess(modalInstance, state);
      }, function() {
          scopeMutateFailure(modalInstance);
          })["finally"](function() {
          modalEventConfig.disableButtonsForRun = false;
      });
  };

  var modalEventConfig = {
    disableButtonsForRun: false,
    statusBar: false,
    nodeStatus: 'Building',
    statusType: 'warning'
  }

  function scopeMutateSuccess(modalInstance, state){
    /////////////////////////////////////////////////
    //THE SCPOPE DATA MEMBERS THAT ARE CHANGED BUT
    //CURRENT DIGEST() DOES NOT INCLUDE THE CHANGE
    modalEventConfig.statusType = 'success';
    modalEventConfig.nodeStatus = 'Completed Successfully';
    //////////////////////////////////////////////////

    $timeout(function() {
      scopeMutateResetValues();
      return modalInstance.close();
    }, TIME_CLOSE_MODAL);
    state.forceReload();
  }




  modalEventConfig.scopeMutateStart = scopeMutateStart;

  modalEventConfig.close = scopeMutateResetValues;

  return {
    runEventCheck: runEventCheck,
    modalEventConfig: modalEventConfig
  };

And here is the controller:

angular.module('main.loadbalancer').controller('EditNodeCtrl', function($scope, $modalInstance, Configuration, LoadBalancerService, NodeService, StatusTrackerService, $state, $q) {
  NodeService.nodeId = $scope.id;
  $q.all([NodeService.getNode(), LoadBalancerService.getLoadBalancer()]).then(function(_arg) {
    var lb, node;
    node = _arg[0], lb = _arg[1];
    $scope.node = node;
    return $scope.save = function() {
      $scope.modalEventConfig.scopeMutateStart();
      return NodeService.updateNode({
        account_number: lb.customer,
        ip: node.address,
        port: node.port_number,
        label: node.label,
        admin_state: node.admin_state,
        comment: node.comment,
        health_strategy: {
          http_request: "" + node.healthMethod + " " + node.healthUri,
          http_response_accept: "200-299"
        },
        vendor_extensions: {}
      }).then(function(eventId) {
        return StatusTrackerService.runEventCheck(lb.customer, eventId,
          $modalInstance, $state);
      });
    }
  });

   $scope.modalEventConfig = StatusTrackerService.modalEventConfig;

The issue I am having is in the service. After a successful resolve in newStatusEvent and scopeMutateSuccess(modalInstance, state); runs... the modalEventConfig.statusType = 'success'; and modalEventConfig.nodeStatus = 'Completed Successfully'; changes aren't reflected in the view.

Normally, this would be because a digest() is needed to make angular.js aware of a change. However, I have verified in the stack(chromium debugger) that a digest() was called earlier in the stack and is still in effect when the scope members are mutated in function scopeMutateSuccess(modalInstance, state);

What is weird, if I add $rootScope.$apply() after modalEventConfig.nodeStatus = 'Completed Successfully';...then Angular.js will complain a digest() is already in progress...BUT...the view will successfully update and reflect the new changes in from the scope members nodeStatus and statusType. But, obviously this is not the answer/appropriate fix.

So, the question is why isn't the digest() that is currently running from the beginning of the stack(stack from chromium debugger) making angular.js aware of the scope changes for modalEventConfig.statusType = 'success' and modalEventConfig.nodeStatus = 'Completed Successfully'? What can I do to fix this?

Upvotes: 0

Views: 78

Answers (2)

dman
dman

Reputation: 11073

Fixed it.

function scopeMutateSuccess(modalInstance, state){ ///////////////////////////////////////////////// //THE SCPOPE DATA MEMBERS THAT ARE CHANGED BUT //CURRENT DIGEST() DOES NOT INCLUDE THE CHANGE modalEventConfig.statusType = 'success'; modalEventConfig.nodeStatus = 'Completed Successfully'; //////////////////////////////////////////////////

    $timeout(function() {
      scopeMutateResetValues();
      state.forceReload();
      return modalInstance.close(); 
    }, TIME_CLOSE_MODAL);

  }

I am using ui-router and I do a refresh with it useing $delegate. I place state.forceReload(); in the $timeout...the scope members update as they should. I have no idea why exactly, but I am glad this painful experience has come to a end.

Upvotes: 0

Pramod Sharma
Pramod Sharma

Reputation: 386

$scope.modalEventConfig = StatusTrackerService.modalEventConfig; is a synchronous call, you need treat things asynchronously . You need wait on promise(resolved by service) at calling area also, i.e. in the controller .

Upvotes: 1

Related Questions