1

I want to dynamically generate the HTML data on my webpage based on data driven values. Ie I want to load a list of environments, a list of models, and then for each model/environment combination, output a row of HTML based on this.

I have used ng-repeat in the past to use a JS collection in my controller to generate the results, ie for each item in the collection, output this block of HTML, which is effectively what I want to do here, albeit with two nested ng-repeats. eg

<tr ng-repeat="model in models">
    <td>
       <div ng-repeat="env in environments">
         {{model.name}} {{env.name}}
       </div>
    </td>
</tr>

My problem though is that I have to call off asynchronously to a REST api to get this data, and so when that returns, it goes into the promise block to handle the results.

Eg

appService.init = function() 
{
    ComputeModelService.getModels()
                .then(function (response, status, headers, config) {
          $scope.models = response.data;
    }

    ComputeModelService.getEnvironments()
                .then(function (response, status, headers, config) {
          $scope.environments = response.data;
    }
}

init()

How do I get the controller to load the data from the REST API in the background, have the UI show a "loading" cursor while it loads, and then render the dynamic HTML when both sets of data come back?

NZJames
  • 4,963
  • 15
  • 50
  • 100

3 Answers3

1

Simply make the rest call as you normally would and bind the structure where you want to store the data to the ng-repeat. Once it's finished, assign it to your scope (you may need to do an $apply if the assignment takes place outside the angular context).

For the loading, you can set a flag to true then false once all the data has loaded (on promise all or whatever). Have your loading icon bound to this with ng-show.

aw04
  • 10,857
  • 10
  • 56
  • 89
0

You need to set ng-show on :

<div ng-show = "models.length > 0">
    <tr ng-repeat="model in models">
        <td>
           <div ng-repeat="env in environments">
             {{model.name}} {{env.name}}
           </div>
        </td>
    </tr>
</div>

and in your js - return a promise .

Community
  • 1
  • 1
Itsik Mauyhas
  • 3,824
  • 14
  • 69
  • 114
0

Keep in mind that services are Singletons. You can set a variable when you instantiate your service. You should also add a setter and getter method so you don't do the same call over and over.

Inject the service in your controller and set what you want there by calling the get method.

Something like this:

angular.module('someModule').service('catService', ($http) => {

        // add categories here
        let categories  = null;

        let returnObj = {
            init: () => {
                returnObj.returnCategories();
            },
            returnCategories: () => {
                let promise = $http.get('/app/categories').then(function (response) {
                    if( response.data ) returnObj.setCategories(response.data);
                    return response.data;
                });
                // Return the promise to the controller
                return promise;
            },
            setCategories: ( data ) =>{
                categories = data;
            },
            getCategories: () => {
                return categories;
            }
        };

        return returnObj;

    });

Then you have to inject that into the controller:

angular.module('someModule')
.controller('yourController', ['$scope', 'catService', ($scope, catService) => {

    // set the libraries property
    $scope.cat = {};
    catService.returnCategories().then( () => {
        $scope.cat= catService.getCategories();
    });

}]);

You can also instantiate this in some other place and then in your controller you can call only the getCategories() method.

Hope this helps. Cheers.

emcee22
  • 1,851
  • 6
  • 23
  • 32