Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - UI Does Not Update Well

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;
            }
          )
  }
}]);

My intent is to iterate through each team and attempt to update the players profile. I want to reflect what is happening in the UI. In an effort to do this, I have the following in my view:

<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 renders correctly initially. However, when the execute button gets clicked, both "Checking..." and "Updated" appear. After a second or two, the word "Checking..." goes away. After some investigation, I learned my web service call is executing in ~90 ms. That would explain why the word "Updated" seems to appear so quickly. However, it does not explain why it takes so long for the word "Checking..." to go away.

Can someone please explain to me what I'm doing wrong?

Thanks!

like image 700
JQuery Mobile Avatar asked Mar 05 '26 08:03

JQuery Mobile


1 Answers

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

In the JavaScript, why not set the status as 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 eliminate the switch from the HTML entirely. 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, really need to have an integer state variable for some reason, then write a little 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);
        }
      )
}
like image 169
Lee Jenkins Avatar answered Mar 06 '26 23:03

Lee Jenkins



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!