AngularJS - UI is not updating

I have an AngularJS app. My controller looks like this:

myApp.controller('MyCtrl', ['$scope', '$http', function ($scope, $http) {
  $scope.items = [];

  // ProfileUpdate: 0=Not Checked, 1=Checked, 2=Failed, 3=Succeeded
  $scope.items.push({
    name: 'Chicago Fire', players: [
      { number: 1, profileUpdated:0, name: 'Bill' },
      { number: 2, profileUpdated:0, name: 'John' }
    ]
  });

  $scope.items.push({
    name: 'Philadelphia Ice', players: [
      { number: 3, profileUpdated:0, name: 'Phil' },
      { number: 4, profileUpdated:0, name: 'Flo' }
    ]
  });

  ...

  $scope.currentTeamIndex = 0;
  $scope.currentPlayerIndex = 0;
  $scope.execute = function() {
        $http.get(playerRelatedUrl)
          .then(
            function(res) {
              $scope.items[$scope.currentTeamIndex].players[$scope.currentPlayerIndex].profileUpdated = 3;
            },
            function(err) {
$scope.items[$scope.currentTeamIndex].players[$scope.currentPlayerIndex].profileUpdated = 2;
            }
          )
  }
}]);

      

I intend to iterate over each team and try to update the player profile. I want to reflect what's going on in the UI. In an attempt to do this, I have the following in my opinion:

<button ng-click="execute()">Execute</button>
<div ng-repeat="team in items">
  <h2>{{team.name}}</h2>
  <div ng-repeat="player in team.players">
    <ul class="list-inline">
      <li>
        <div ng-switch="player.profileUpdated">
          <h3 ng-switch-when="0">Not checked yet</h3>
          <h3 ng-switch-when="1">Checking...</h3>
          <h3 ng-switch-when="2">Unable to update</h3>
          <h3 ng-switch-when="3">Updated!</h3>
        </div>
      </li>
      <li>{{player.name}}</li>
    </ul>
  </div>
</div>

      

This code displays correctly. However, when the execute button is clicked, both "Checking ..." and "Updated" appear. After a second or two, the word "Checking ..." disappears. After some investigation, I found out that my web service call is executing in ~ 90ms. This explains why the word "Updated" seems so fast. However, he does not explain why it took so long for the word "Checking ..." to disappear.

Can someone explain to me what I am doing wrong?

Thank!

+3


source to share


2 answers


The angularJS $ http service returns a "promise" which means it will immediately return a placeholder type for the return value, but that placeholder will eventually be filled with the actual return value. That is when the web service responds. Even if your web service call takes 90ms, it doesn't necessarily mean that the promise has received its true value. It probably depends a little on how you measured, but it could be the mechanism of the delays you are experiencing. See https://docs.angularjs.org/api/ng/service/$http for reference.



0


source


Sometimes you have to work with the constraints of the framework. In this case, there is actually a potentially simpler solution.

In JavaScript, why not set the status to be a string instead of an integer?

$scope.execute = function() {
    $http.get(playerRelatedUrl)
      .then(
        function(res) {
                                                              // NOTICE THE STATUS IS A STRING HERE vvvvvvvvv
            $scope.items[$scope.currentTeamIndex].players[$scope.currentPlayerIndex].profileStatus= "Updated";
        },
        function(err) {
            $scope.items[$scope.currentTeamIndex].players[$scope.currentPlayerIndex].profileStatus = "Unable to update";
        }
      )
}

      

Then completely disconnect the switch from HTML. The code becomes much easier to read.



<button ng-click="execute()">Execute</button>
<div ng-repeat="team in items">
  <h2>{{team.name}}</h2>
  <div ng-repeat="player in team.players">
    <ul class="list-inline">
      <li>
        <div>
          <h3>{{player.profileStatus}}</h3>
        </div>
      </li>
      <li>{{player.name}}</li>
    </ul>
  </div>
</div>

      

If you really need to really have an integer state variable for some reason, then write a small function and just do both:

function updatePlayerStatus( newValue ) {
    var statusUpdateStrings = [ "Not checking", "Checking", ... etc. ];
    var player = $scope.items[$scope.currentTeamIndex].players[$scope.currentPlayerIndex];
    player.profileUpdated = newValue;
    player.profileStatus= statusUpdateStrings[ player.profileUpdated ];
}

$scope.execute = function() {
    $http.get(playerRelatedUrl)
      .then(
        function(res) {
            updatePlayerStatus(3);
        },
        function(err) {
            updatePlayerStatus(2);
        }
      )
}

      

+2


source







All Articles