0

I am trying to refactor some code out of my controller and into the route's 'resolve' and am having trouble getting the correct return value from resolve. I think the problem is either due to my misunderstanding of js closures or the $q library in angular.

In the routing:

.when('/countries/:id', {
      templateUrl: 'country/country.html',
      controller: 'countryCtrl',
      resolve: {
        ActiveCountry: ['CountryData', '$q', '$route', function(CountryData, $q, $route) {
          var defer = $q.defer();
          CountryData($route.current.params.id).then(function(data){
            console.log(data);
            defer.resolve(data);
          });
          return defer.promise;
        }]
      }
    })

The console.log in this block returns the correct JSON object from the api call. However, when it is passed into the controller, the controller returns the function from the CountryData service:

.controller('countryCtrl', [
  'CountryData',
  '$routeParams',
  '$scope',
  function (ActiveCountry, $routeParams, $scope) {
    var countryId = $routeParams.id;
    console.log(ActiveCountry);
    $scope.mapId = $routeParams.id.toLowerCase();
    $scope.country = ActiveCountry;
  }
]);

The value of the routing console.log is: Object {countryName: "Spain", currencyCode: "EUR", fipsCode: "SP", countryCode: "ES", isoNumeric: "724"…}

but the controller console log is the function from my CountryData service:

function (countryId) {
      var defer = $q.defer();
      $http.get(COUNTRIES_PATH + '&country=' + countryId + API_AUTH, { cache: true }).success(function (data) {
        defer.resolve(data.geonames[0]);
      });
      return defer.promise;
    } 

Why is the object from the routing not being passed into the controller correctly?

Also, why do I need to use $q in the router when it is already built into the CountryData service? Without using $q in the routing, it returns the function rather than the function's return value.

1
  • why do I need to use $q in the router when it is already built into the CountryData service You don't have to. Just make CountryData return promise. Commented Jun 26, 2014 at 5:35

2 Answers 2

1

You put 'CountryData' and then ActiveCountry for your controller arguments. So they do not match up.

It should be 'CountryData' and CountryData

controller('countryCtrl', [
  'CountryData',
  '$routeParams',
  '$scope',
  function (CountryData, $routeParams, $scope) {
    var countryId = $routeParams.id;
    console.log(ActiveCountry);
    $scope.mapId = $routeParams.id.toLowerCase();
    $scope.country = ActiveCountry;
  }
]);
Sign up to request clarification or add additional context in comments.

1 Comment

nice catch! starred at this for a few hours
1

Angular will automatically resolve any promises that are returned from functions on the resolve property. So, your resolve property should look like this:

resolve: {
  ActiveCountry: ['CountryData', '$q', '$route', function(CountryData, $q, $route) {
    return CountryData($route.current.params.id);
  }
}

Before invoking your controller method $routeProvider will resole all promises that are passed as parameters to the controller. For more information, see $routeProvider.when().

1 Comment

looks like maybe the problem is in my service? If I set the resolve to console.log(CountryData($route.current.params.id); it does not log the return value, but the function itself: Object {then: function, catch: function, finally: function} However, in Chrome console network I can see that the service is making the api call as it should.

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.