user202925
user202925

Reputation: 521

How to wait until data is loaded in AngularJS?

In my app I have some data that I fetch from a service that I then proceed to use in my code to preload a form. However, sometimes the data isn't loaded until after the rest of the code is run, so the form comes up blank. Other times, it's fine and everything loads. I want to make it such that it always loads the form with all fields populated.

The problem is that I have multiple service calls, so how do I make sure that all services have finished loading? Here is my code:

In Reference Data Service (the rest of the GETs pretty much use the same kind of code):

        factory.getAllOffices= function(){
          var deferred = $q.defer();
          $http.get(APP_CONFIG.refURL+"/reference/getAllOffices")
            .success(function(response){
                deferred.resolve(response);
            })
            .error(function(msg, code, headers, config){
                console.log(msg);
                deferred.reject(msg);
            });
        return deferred.promise;
    };

In the controller:

    referenceDataService.getAllOffices().then(function(data){
        $scope.allOffices= data;
    });

    referenceDataService.getAllTypes().then(function(data){
        $scope.allTypes= data;
    });

    referenceDataService.getAllTeams().then(function(data){
        $scope.teamOptions.data = data;
    });

    //Checking to see if form exists.
    $scope.formID= '';

    if(!angular.isUndefinedOrNull($routeParams.id)){
        $scope.formID= $routeParams.id.substring(1);
    }

    if (!($scope.formID== '')){
        addFormService.getForm($scope.formID).then(function(data) {

            var officeIndex=angular.findIndexOf($scope.allOffices, data.officeID);
            var typeIndex=angular.findIndexOf($scope.allTypes, data.typeID);

            $scope.form.name= data.name;
            $scope.report.office= $scope.allOffices[officeIndex];
            $scope.report.type= $scope.allTypes[typeIndex];
            $scope.teamOptions.data = data.teamList;
            $scope.report.teams= data.teams;

            angular.forEach($scope.report.teams, function(id) {
                $scope.teamOptions.grid.rows.map(function (row) {
                    if (row.entity.id == id) {
                        row.setSelected(true);
                    }
                });
            });
        });
    }

Sometimes Offices, Types, and Teams aren't returned before the formID code runs.

Upvotes: 5

Views: 10685

Answers (1)

Mark C.
Mark C.

Reputation: 6450

You can use q.all(), as it accepts an array of promises that will only be resolved when all of the promises have been resolved.

$q.all([
      referenceDataService.getAllTypes(),
      referenceDataService.getAllTeams()
    ]).then(function(data){
      $scope.allTypes = data[0];
      $scope.teamOptions.data = data[1];
 });

You can also choose when to show/hide certain elements using ng-hide/ng-show. You can initialize the page with $scope.showProperty = false; and once your service calls have resolved, switch it: $scope.showProperty = true;.

Upvotes: 6

Related Questions