Jonathan Szekely Jonathan Szekely - 4 months ago 16
AngularJS Question

Angular service returns empty object

I've been trying to make a pretty and user friendly app in angular and i'm at the part where i let the user know stuff is loading when i make ajax requests. What i'm trying to accomplish : i want to create a service that handles the initialization data fetching and pass the data as an object to my controller when it becomes available. Of course, the view isn't displayed until all the initial data my controller needs is available. Here's what i have so far:

app.js

var Application = angular.module('ReporterApplication', ['ngRoute']);

Application.service('Initialize', ['$http', '$q', '$timeout', function($http, $q, $timeout)
{

this.serverData = function()
{
$http.get('/packing/scan.action')
.success(function(data)
{
return data;
})
.error(function(data)
{
return data;
});

};

}])


Application.config(['$routeProvider', '$interpolateProvider',

function($routeProvider, $interpolateProvider) {

$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');

$routeProvider

.when('/packing/scan.html', {
templateUrl: 'packing/scan.html',
controller: 'PackingScanController as packer',
resolve: {

initData : 'Initialize' .... etc more code


scan.js

Application.controller('PackingScanController', ['$scope', '$http', 'initData', function($scope, $http, initData) {

var packer = this;

packer.packedToday = initData.serverData(); ... etc more code

Answer

If you want your controller to wait, what you need to do is to configure the resolve option correctly. For this, you need to have your service return a promise, otherwise the router will not wait.

resolve - {Object.<string, function>=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated.


Here's a simplified example:

app.service('Initialize', ['$http', function($http) {
  this.serverData = function()
  {
    // return the http promise
    return $http
      .get('config.json')
      // use success/error if needed
      .then(function (response) {
        // make sure, only the response data is used
        return response.data;
      })
    ;
  };
}]);

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/', {
      template: '<pre>{{ main.initData|json }}</pre>',
      controller: 'MainCtrl as main',
      resolve: {
        // configure with DI
        initData: ['Initialize', function (Initialize) {
          // call the service method, and return the promise
          return Initialize.serverData();
        }]
      }
    })
  ;
}]);

app.controller('MainCtrl', function (initData) {
  // initData will be loaded
  this.initData = initData;
});

demo: http://plnkr.co/edit/sOwyHz4yMvwujBWYzOn0?p=preview

Comments