0

I have several screens and controllers relying on data from servers. Thus I'd like to resolve the data dependency through the router resolve functionality to let it take care that all data is available through promises before rendering the screen. However, I'm not sure if I understood the usage correctly since the following example seems not to work. Why?

angular.module('app',['ngRoute'])
    .service('Data1', function ($q, $routeProvider, $http) {
        var self = this;

        this.fetch = function() {return $http.get('/json/data1',{id:$routeProvider.id})}
    }
    .service('Data2', function ($q, $routeProvider, $http) {
        var self = this;
        this.fetch = function() {return $http.get('/json/data2',{id:$routeProvider.id})}
    }
    .config(function($routeProvider){
        §routeProvider.when('/:id',{
            controller:'TestCtrl',
            templateUrl:'template.html',
            resolve: {
                data1: function (Data1) { return Data1.fetch(); },
                data1: function (Data2) { return Data2.fetch(); }
            }

        });
    })
    .controller('TestCtrl', function($location, $routeParams, $http, data1,data2) {
        console.log(data1);
        console.log(data2);
    });
4
  • Just so I understand, you're wanting to use the resolve property on $routeProvider routes to load the data from your services and then inject them into your controller? Commented Apr 16, 2015 at 15:25
  • Correctly thats what i want to do Commented Apr 16, 2015 at 15:26
  • Or is this a bad idea? Commented Apr 16, 2015 at 15:27
  • No, that's perfectly reasonable. They built functionality specifically for that. I'm writing up an example now for you. Commented Apr 16, 2015 at 15:33

1 Answer 1

1

Here's an example of how to use resolve with $routeProvider properly. First, I defined two factories like you have there, then in my config I set up a route that I want to inject data from my factories in to. I tell it what controller I want to use, the template is non-consequential in this context. Then under resolve I give it an object with two properties that are functions, someData and someMoreData. On those two functions I inject my data1 and data2 factories and $routeParams, get the data from the factories, and return the data.

In my controller definition I tell it I want to inject $scope and then I tell it I want to inject two other things, these are the resolve properties I defined in $routeProvider.

One thing to be mindful of, if you're doing actual API calls in your factories that you want data resolved from, the page will not load until the data is resolved, the controller won't even initiate until those are all done. So you might want to come up with some way to do a loading animation, there are lots of examples here on StackOverflow of how to do that.

angular.module('app.factories', [])
  .factory('data1', ['$q', '$timeout', function($q, $timeout) {
    return {
      getData: function(id) {
        var deferred = $q.defer();
        var promise = deferred.promise;
        
        $timeout(function() {
          deferred.resolve('this is factory 1, id: ' + id);
        }, 2000);
        
        return promise;
      }
    };
  }])
  .factory('data2', ['$q', '$timeout', function($q, $timeout) {
    return {
      getData: function(id) {
        var deferred = $q.defer();
        var promise = deferred.promise;
        
        $timeout(function() {
          deferred.resolve('this is factory 2, id: ' + id);
        }, 2000);
        
        return promise;
      }
    };
  }]);

angular.module('app', ['ngRoute', 'app.factories'])
  .config(['$routeProvider',
    function($routeProvider) {
      $routeProvider
        .when('/', {
          controller: 'defaultCtrl',
          template:'<a href="#/1">Go to route with parameter on it</a>'
        })
        .when('/:id', {
          controller: 'testCtrl',
          template: '<span ng-bind="string1"></span><br /><span ng-bind="string2"></span>',
          resolve: {
            someData: ['data1', '$route',
              function(data1, $route) {
                console.log('resolving someData');
                return data1.getData($route.current.params.id).then(
                  function(response) {
                    return response;
                  });
              }
            ],
            someMoreData: ['data2', '$route',
              function(data2, $route) {
                console.log('resolving someMoreData');
                return data2.getData($route.current.params.id).then(
                  function(response) {
                    return response;
                  });
              }
            ]
          }
        });
    }
  ])
  .controller('defaultCtrl', function() { })
  .controller('testCtrl', ['$scope', 'someData', 'someMoreData',
    function($scope, someData, someMoreData) {
      console.log('in route with id param');
      $scope.string1 = someData;
      $scope.string2 = someMoreData;
    }
  ]);
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-route.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
  <div ng-view>

  </div>
</body>

</html>

Edit Modified it so that your factories are in their own module and injected as a dependency to the app module, rather than being on the app module itself, which is IMHO leaning towards better architecture (most of the time I give each individual factory it's own module, but for brevity's sake I kept it simple)

Sign up to request clarification or add additional context in comments.

2 Comments

THX Ben, as I read resolve can handle the promises of $http and I was wondering how to use them?
I've edited my answer to show an example of using promises, hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.