'Preload Large Amounts of Datasets Before Attempting to Set Drop Down List Values

I'm attempting to load a rather large form (over 300 fields) on an angularjs razor page and I'm just struggling with it (I've only been learning and working with angularjs for 2 months).

The form has over 2 dozen drop down lists (I'm using angularjs-dropdown-multiselect.js for my controls) that depend on datasets that are being pulled from a service. I think need to pull a record of for the form they are loading that has all of the saved values for the form. Then I set the selected value of each of the drop down lists. The problem is, that my http.gets are not fully returned when the code executes to set the drop down list selected model. This results in an error. Sometimes I can get 15 or 16 of the datasets to pop before the code is executed to set the drop down list model, but it's variable depending on network traffic.

Is there any way to preload my data before the rest of the controller code executes? I've tried using this for my get calls.

$http.get(myURL+ 'ProductsGet/' + ContactId)
        .then(function (response) {
            $scope.products = response.data;
        })
        .catch(function (data){
            $window.alert(data.xhrStatus);
        });

Then this is where my code has a problem because the $scope.products is not actually set yet when this executes. The $scope.ds is set with another http.get data call.

  if ($scope.ds.productId!= null) {
                var prod = $filter('filter')($scope.products, function (value) { return value.productId === $scope.ds.productId; })
                $scope.productModel.push(prod[0]);
            }

I've tried putting all of my data calls into a data factory and then using setting the $scope.products = dataFactory.GetProducts() but this still doesn't stop the controller code from executing so it plows right on through into the code that sets the drop down lists values. I've tried using my own custom promise function:

   cachePromise = function () {
        var defer = $q.defer();
        $http.get(myURL+ 'ProductsGet/' + ContactId)
           .then(function (response) {
                $scope.products = response.data;
            })
            .catch(function (data){
                $window.alert(data.xhrStatus);
            });

 
       return defer.promise;
  };

   var init = function () {
       cachePromise().then(function succes() {
        if ($scope.profileId!= null) {
            $scope.view = 'Update';
            LoadProfileInformation();
        };
  };

 init();

But the init function executes, it triggers the http.gets in the cachePromise function, but continues on into the LoadProfileInformation() function where I am seting the drop down list models based on my datasets and it fails because the gets haven't all returned data.

I tried setting up a $stateProvider using ui-router, but I kept getting errors trying to access the resolve function in the state provider from within my controller. Here's an example of the state provider I tried used a dataset of franchiseTypes. I kept getting an error that the franchiseTypeProvider was not defined.

var app = angular.module("myApp", ['ngResource', 'ngAnimate', 'ngTouch', 'ngSanitize', 'ui.bootstrap', 'angularjs-dropdown-multiselect', 'ui.grid', 'ui.router' ]);

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.useXDomain = true;
    $httpProvider.defaults.withCredentials = false;
    delete $httpProvider.defaults.headers.common["X-Requested-With"];
    $httpProvider.defaults.headers.common["Accept"] = "application/json";
    $httpProvider.defaults.headers.common["Content-Type"] = "application/json; charset=utf-8";
}
]);

app.config(['$stateProvider', '$urlRouterProvider',

    function ($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('MyPage', {
                url: '/MyPage',
                controller: 'InformationCtrl',
                resolve: {
                    franchiseTypes: function ($http) {
                        return $http({ method: "GET", url: myServiceURL + 'FranchiseTypesGet/' + sessionStorage.getItem('Id') });
                    }
                }
            });
    }

]);
app.controller("InformationCtrl", ['$scope', 'franchiseTypes', '$http', '$window', '$location', '$anchorScroll', '$filter', function ($scope, $http, $window, $location, $anchorScroll, $filter, franchiseTypes) {

//this is set as the source of one of my multi-select drop down lists
 $scope.franchiseTypeModel = [];

 $scope.franchiseTypes = franchiseTypes;

//$scope.ds is loaded through a http get request 
 if ($scope.ds.FranchiseTypeId != null) {
    //this is what was failing in my original code because my data is not completely loaded by the time this code executes
    var fran = $filter('filter')($scope.franchiseTypes, function (value) { return value.FranchiseTypeId === $scope.ds.FranchiseTypeId ; })
    $scope.franchiseTypeModel.push(fran[0]);
  }
}]);

Sorry for all of the code samples, I've been trying things for about two weeks now and can't get this to work. My background is webforms and winforms where a line of code wouldn't be executed before the previously line of code is completely executed so trying to work with angularjs has been an interesting challenge.



Solution 1:[1]

A helpful person on Reddit pointed me in the right direction. I ended up using something like this, with some of the get()s chained since one get() relies on the data from another get(). Posting this in case this helps someone else. I had tried chaining promises previously, but I wasn't sure how to use promises with $q.all, and still access the data returned from the promise.

This does everything I need it to. I just have all 20+ data calls added the the cachePromises array and then the LoadDataFields does not execute until they are all complete.

    $scope.cachePromises = [];
    $scope.cachePromises.push($http.get(myURL+ 'ProductGet/' + ContactId)
            .then(function (response) {
                $scope.products = response.data;
            })
            .catch(function (error) {
                $window.alert(error);
            })
    );
    
    $q.all($scope.cachePromises).then(function () {
           LoadDataFields();
    });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeremy Caney