-1

I have seen this issue a lot on SO, but none of the solutions I have tried are working for me. I tried using $apply() which gives me an error stating that the digest cycle is already running. I tried using the Dot "." notation, but nothing changes. I even tried using timeout and promises, but still it does not update in the view.

Here is the HTML:

<th colspan="4" ng-class="{'ssqtrue': deficiencies === false , 'ssqfalse': deficiencies === true}">
<span ng-model="definfo">{{definfo}}</span>
    </th>

Here is my Controller code:

    $scope.recalculateDashboard = function (goToDashboard) {
    contractorService
      .calculateScores()
      .success(function () {
          getscoringDetails();
          getDefInfo();
          if (goToDashboard) {
              $scope.tabs[0].active = true;
          }
      }).error(function (reason) {
          console && console.log(reason.statusText);
          genericErrorAlertHandler();


      });
};

function getDefInfo() {
    contractorService.getDeficiencyInfo()
      .success(function (data) {
            $scope.$apply(function() {
                $scope.definfo = data;
            });
          if ($scope.definfo == 'No Deficiencies Found') {
              $scope.deficiencies = false;
          } else {
              $scope.deficiencies = true;
          }
      }).error(function (reason) {
          console && console.log(reason.statusText);
          genericErrorAlertHandler();


      });
}

For the life of me, I can't figure out what is going on here. Any assistance is greatly appreciated!

Rani Radcliff
  • 4,856
  • 5
  • 33
  • 60
  • You can not bind `ng-model` to `span`, and use `then` function instead of `success` because it deprecated. – Hadi J Aug 17 '17 at 17:55
  • Read the difference between [ng-model and ng-bind](https://stackoverflow.com/a/12420157/5447994) – Thamilhan Aug 17 '17 at 17:57
  • ng-bind was there first and wasn't working so I changed it to ng-model – Rani Radcliff Aug 17 '17 at 18:00
  • Please post `getDeficiencyInfo` logic for full picture – Maxim Shoustin Aug 17 '17 at 18:04
  • getDeficiencyInfo is an $http call in my service. this.getDeficiencyInfo = function () { return $http.get('/SSQV4/SSQV5/Contractor/GetDeficiencyInfo'); }; – Rani Radcliff Aug 17 '17 at 18:09
  • @RaniRadcliff are you able to reproduce it outside of your project? Possibly create a fiddle and show us the full picture please, since your code looks good except the points mentioned by Maxim. – Stanislav Kvitash Aug 17 '17 at 18:18
  • If I knew how to "fake" the service in a Plunker I could, but I don't know how. The only thing that comes back from the service is a string returned by the database. It either has a number like" 3 Deficiencies Found" or "No Deficiencies Found". – Rani Radcliff Aug 17 '17 at 18:28
  • @RaniRadcliff you don't need to 'fake'. Just take some dummy URL that returns JSON response, in my example I took from Google maps location – Maxim Shoustin Aug 17 '17 at 18:29

2 Answers2

0

Regards to <span ng-model="definfo">{{definfo}}</span>

You don't need ng-model directive here. Enough to use {{definfo}} or better way like folks pointed to use ng-bind like:

<span ng-bind="definfo"></span>

I tried using $apply() which gives me an error

Generally, developers use $scope.$apply when get callback from 3d party code like jQuery that stay out of digest cycle. So don't use it. BTW, safety way is to use $timeout for example a.e. wrap as:

 $timeout(function () {
   $scope.definfo = data;
 }); 

I believe if you don't use Promise chain you can use success and error callbacks (what you actually did) instead to use then()


About $http.get('/SSQV4/SSQV5/Contractor/GetDeficiencyInfo');

$http.get returns original Promise but it also returns status 'Ok', config, headers ... and i'm sure you don't want parse full response in your controller. So I would create new Promise in your service and fetch results only.

So instead: return $http.get(URL); I would write in Service:

  this.getDeficiencyInfo = function () {          
  var deferred = $q.defer(); 
      $http({method: 'GET', url: URL}).then(function(res){
         deferred.resolve(res.data); 
      }, function (error) {
            console.error(error);
            deferred.resolve({error:error}); //actually you can reject
        });    
     return deferred.promise;
  };

DEMO in fiddle

Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • I probably should have stated that I already tried using timeout as well with no difference. I'll add that to my description. Thanks. – Rani Radcliff Aug 17 '17 at 18:07
  • my original Html was . I thought adding the model might help. – Rani Radcliff Aug 17 '17 at 18:10
  • I hate that people can down vote your answer anonymously. It is equivalent to throwing stones and hiding your hands. SO should make a rule that if you down vote a question or answer you have to supply the submitter with an explanation. On another note, do you know why the scope variable would change after being set by the original variable? I am assuming that there must be some logically reason. Thanks for all of your help by the way. – Rani Radcliff Aug 18 '17 at 12:00
0

I figured this out, although I don't know "why" it caused this particular issue. When the page first loads $scope.definfo is set by a variable from another http call. The variable var pagedata = [] holds a lot of information that comes back from the service when the page is first rendered. The scope variable is then set with this code: $scope.definfo = pagedata.DeficiencyInfo. Removing that line and calling the function getDefInfo directly, sets and updates the scope variable as desired. Perhaps one of you gurus could explain why that is to me and others so that it may help others. Thank you to everyone for your help.

Rani Radcliff
  • 4,856
  • 5
  • 33
  • 60