ng-repeat list doesn't update immediately after api call

568 Views Asked by At

My web app view lists folders and their children in a nested list:

<ul>
  <li class="folderLi" ng-repeat="folder in folders">
    <a href="" ng-click="listFolderFiles( folder )">{{folder.title}}</a>
    <ul >
      <li ng-repeat="child in folder.children">
          {{child.title}}
      </li>
    </ul>
  </li>
</ul>

When I load the initial list of folders, the list updates immediately to display the folders. However, there is no children object on each folder at that point. That is filled out when the folder is clicked and the app calls the Google Drive API to retrieve the folder's children. The controller includes this function:

$scope.listFolderFiles = function( folder ) {
  var request = gapi.client.request({
    'path': '/drive/v2/files',
    'method': 'GET',
    'params' : {
        'q' : "'" + folder.id + "' in parents"
      }
  });


request.then(function(response){
     //log successful response
     console.log(response);
     folder.children = response.result.items;
           }, function(response) {
     //log error
      console.log(response);
   })
  }

This function correctly retrieves the information and updates the model. However, the ng-repeat list of children is not updated and displayed immediately. Instead, it is updated and displayed the next time a folder is clicked. It seems like this function is updating the view before the api call is finished, so the next time the function runs the view gets updated to show the last API call's response. Thoughts?

1

There are 1 best solutions below

6
On

You are trying to update outside angular's knowledge. So your view is not updated. You need to use $scope.$apply() or $timeout to run a digest cycle.

request.then(function(response){
     //log successful response
     console.log(response);
     //folder.children = response.result.items; //Required in case of $scope.$apply()
     $timeout(function(){folder.children = response.result.items;}); //Or $scope.$apply(); (Don't forget to inject $timeout in your controller)
           }, function(response) {
     //log error
      console.log(response);
   })
  }