Reputation: 147
I have declared a state using ui-router and am trying to perform a resolve. However, I cannot return a value in my resolve using a $http in a factory. Below is one way that I've tried.
It appears that the success
callback runs too late so that nothing is actually returned inside the resolve. When the success
callback does run, it produces the desired result.
...
.state('book', {
url: '/book',
abstract: true,
views: {
'': {
templateUrl: 'templates/book.html',
controller: bookController
}
}
})
.state('book.detail', {
url: '/{chapter}/{pageName}',
resolve: {
pageIdNumber: ['$http','$stateParams', 'myFactory', function($http, $stateParams, myFactory) {
return myFactory.getPageIdNumberUsingPageName(
function(response, $stateParams) {return response[0];}, // console.log(response[0]) gives the desired result but nothing is returned. I think this function runs too late.
function(response) {return response[0];},
$stateParams.pageName);
}]
},
views: {
'page@book': {
templateUrl: 'templates/page.html',
controller: pageController
}
}
})
...
myFactory.$inject = ['$http'];
function myFactory($http){
return {
getPageIdNumberUsingPageName: function (callbackSuccess, callbackError, pageName){
$http({
method: 'POST',
url: 'http://example.com/api/get_page_id.json',
cache: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
data: 'page_name=' + encodeURIComponent(pageName),
})
.success(function (response) {
callbackSuccess(response);
})
.error(function (response) {
callbackError(response);
});
}
};
}
Upvotes: 1
Views: 872
Reputation: 147
In the resolve
, you must return a promise
object - you cannot return a value:
...
.state('book.detail', {
url: '/{chapter}/{pageName}',
resolve: {
pageIdNumber: ['$http','$stateParams', 'myFactory', function($http, $stateParams, myFactory) {
return $something; // $something must be a promise object and not a value like "2" or "dog".
}]
},
...
However, the code provided in the question uses a factory to retrieve a value. We must change the factory so that it retrieves a promise
. To do this, we note that the success
method returns values and the then
method returns a promise:
function myFactory($http){
return {
getPageIdNumberUsingPageName: function (callbackSuccess, callbackError, pageName){
$http({
...
})
.success(function (response) {
// response contains values like "2" and/or "dog"
});
}
};
}
function myFactory($http){
return {
getPageIdNumberUsingPageName: function (callbackSuccess, callbackError, pageName){
$http({
...
})
.then(function (response) {
// response contains a promise object that, when eventually fulfilled, will produce values like "2" and/or "dog"
});
}
};
}
So, the factory changes to:
myFactory.$inject = ['$http'];
function myFactory($http){
return {
getPageIdNumberUsingPageName: function (pageName){
return $http({ // notice the "return" here
method: 'POST',
url: 'http://example.com/api/get_page_id.json',
cache: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
data: 'page_name=' + encodeURIComponent(pageName),
})
.then(function (response) {
return response.data[0]; // data[0] contains the value that I want. response is a promise object
});
}
};
}
And the resolve
becomes (read the comments in the code):
...
.state('book.detail', {
url: '/{chapter}/{pageName}',
resolve: {
pageIdNumber: ['$http','$stateParams', 'myFactory', function($http, $stateParams, myFactory) {
return myFactory.getPageIdNumberUsingPageName($stateParams.pageName); // this returns the $http object in the factory; that factory in turn returns the promise object.
}]
},
views: {
'page@book': {
templateUrl: 'templates/page.html',
controller: pageController
}
}
...
Upvotes: 2