Reputation: 9925
I came across this situation where I can see $stateParams gets populated in one place but not in another. I'm kind of newbie to angular-ui-router so any help will be appreciated.Thanks !
In the resolve block of the following state, I injected $stateParams as a dependency in the function for data 'campaign' and the $stateParams is populated.
.state('campaign', {
url: "/campaign/{campaignId:int}",
templateUrl: campaign_template,
controller: 'CampaignCtrl',
parent: 'org',
abstract: true,
resolve: {
campaign: function(CampaignService, $stateParams) {
console.log('$stateParams is populated here!', $stateParams)
return CampaignService.get($stateParams.campaignId)
.then(function(campaign) {
return campaign;
});
}
}
Inside the CampaignService function, however, I require $stateParams but it's empty. I'm confused because I'm assuming since it's populated when I injected it in the resolve block, it should be the same no matter where else I get it again.
.service('CampaignService', function($injector, $q) {
this.get = function() {
var $stateParams = $injector.get('$stateParams');
console.log('$stateParams is empty here!', $stateParams);
var deferred = $q.defer();
setTimeout(function() {
deferred.resolve({
name: 'campaignName'
});
}, 1000);
return deferred.promise;
}
})
Upvotes: 2
Views: 156
Reputation: 48968
I'm assuming since it's populated when I injected it in the resolve block, it should be the same no matter where else I get it again.
The $stateParams
injected into the resolve block is the proposed future state. At that point in time the application is still using the old state. And will remain in the old state if any of the resolve promises are rejected.
Under the hood, the $state
service creates a local version of $stateParams
that it injects in the resolve function:
var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); var locals = { $stateParams: $stateParams }; // Resolve 'global' dependencies for the state, i.e. those not specific to a view. // We're also including $stateParams in this; that way the parameters are restricted // to the set that should be visible to the state, and are independent of when we update // the global $state and $stateParams values. dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); var promises = [dst.resolve.then(function (globals) { dst.globals = globals; })];
— https://github.com/angular-ui/ui-router/blob/legacy/src/state.js#L1427-L1437
The solution is to pass the proposed future $stateParams
to the service.
Upvotes: 1
Reputation: 3121
Your service probably shouldn't care about state parameters. You are already passing in the campaignId
value inside of your state definition so in order to consume that within the service you could modify it like this:
.service('CampaignService', function($injector, $q) {
this.get = function(campaignId) {
console.log('campaignId = ' + campaignId);
var deferred = $q.defer();
setTimeout(function() {
deferred.resolve({
name: 'campaignName'
});
}, 1000);
return deferred.promise;
}
})
Upvotes: 1