Reputation: 802
I'm developing the angular app, using ui - router.
I created root state which is an abstract one aimed to resolve async. dependencies.
So every sub states from my perspective should be able to use those dependencies in own resolve state properties.
So if abstract
root state resolving async dependencies and sub state also resolving asyc dependencies, the latter one should wait for the root dependencies to resolved, before starting its own resolve
method. Right?
Here is the code example, that shows what I mean:
async, promise based methods that are used inside corresponding resolve
public iAmInTheRootState(): IPromise<any> {
let deferred = this._$q.defer();
this._$timeout(() => {
deferred.resolve();
}, 3000);
return <IPromise<any>> deferred.promise;
}
public iAmInTheSubState(): IPromise<any> {
let deferred = this._$q.defer();
this._$timeout(() => {
deferred.resolve();
}, 100);
return <IPromise<any>> deferred.promise;
}
Root abstract state:
$stateProvider
.state('app', {
url: '/',
abstract: true,
templateUrl: 'layout/app-view.html',
resolve: {
auth: function (Auth: IAuthService) {
'ngInject';
return Auth.iAmInTheRootState().then(() => {
console.log('I am the root state, so I should be first');
});
}
}
});
Sub state which is the daughter state:
$stateProvider.state('app.my-calls', {
url: '',
controller: 'MyCallsController',
controllerAs: '$ctrl',
templateUrl: 'states/my-calls/my-calls.html',
resolve: {
secondAuth: (Auth: IAuthService) => {
'ngInject';
return Auth.iAmInTheSubState().then( () => {
console.log('although I am faster I should be second because i am in the sub state');
});
}
}
})
But the output differs from my expectations:
Upvotes: 0
Views: 266
Reputation: 802
Although Tim's answer can be considered as a direct response to my question, one may want to understand how to make sub states to wait for their parent's resolve method.
Check out the github issue regarding to this topic.
So in short: sub states should have parent state as a dependency:
Parent State:
$stateProvider
.state('app', {
url: '/',
abstract: true,
templateUrl: 'layout/app-view.html',
resolve: {
ParentAuth: function (Auth: IAuthService) {
'ngInject';
return Auth.iAmInTheRootState().then(() => {
console.log('I am the root state, so I should be first');
});
}
}
});
Child state:
$stateProvider.state('app.my-calls', {
url: '',
controller: 'MyCallsController',
controllerAs: '$ctrl',
templateUrl: 'states/my-calls/my-calls.html',
resolve: {
SubAuth: (ParentAuth, Auth: IAuthService) => {
'ngInject';
return Auth.iAmInTheSubState().then( () => {
console.log('although I am faster I should be second because i am in the sub state');
});
}
}
})
Upvotes: 0
Reputation: 151
In your example, the 'app.my-calls' is indeed created after the 'app' state (you can verify this by logging the onEnter callback.)
Resolve
You can use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.
If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.
The resolve callback is not used to delay the state creation, but used to delay the controler creation.
To understand the full flow, you can log the $stateChangeStart & $stateChangeSuccess events.
Upvotes: 2