Reputation: 3068
UI-Router triggers route change as defined in config section before App_Initializer
function is executed. In the below example home state's resolveFn
is triggered before App_Initialzer's
resolves.
How to solve this?
app.module.ts
@NgModule({
declarations: [
AppComponent,
routingComponents
],
imports: [
BrowserModule,
UIRouterModule.forRoot(
{ states: appRoutes,
useHash: true ,
config: uiRouterConfigFn
}
),
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: test,
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
function test(): Function {
return () => delay();
}
function delay(){
var deferred = new Deferred<any>();
console.log("Initialization started: " + new Date());
setTimeout(() => {
console.log("Initialization Done: " + new Date());
deferred.resolve();
}, 5000); // Wait 3s then resolve.
return deferred.promise;
}
app.routes.ts
export const routingComponents = [
HomeComponent
];
let home = {
name: 'home',
url: '/home',
component: HomeComponent,
resolve:[
{
token: 'te',
resolveFn:($state: StateService) =>{
var deferred = new Deferred<any>();
console.log("testing Home Component");
deferred.resolve();
return deferred.promise;
}
}
]
}
export const appRoutes = [
home
];
export function uiRouterConfigFn(router: UIRouter, injector: Injector) {
// If no URL matches, go to the `hello` state by default
router.urlService.rules.otherwise({ state: 'home' });
}
Upvotes: 2
Views: 1433
Reputation: 16675
For anyone else who needs to solve this problem, you can use UIRouterModule
's deferIntercept()
method to prevent routes from initializing before APP_INITIALIZER
has resolved. (Per Christopher Thielen (@ UIRouter): https://github.com/ui-router/angular/issues/206)
I was able to solve this issue by setting deferIntercept
to true
in app.module
:
@NgModule({
imports: [
/* Other modules ... */
UIRouterModule.forRoot({
states: [
/* States (routes) ...*/
],
config: uiRouterConfigFn,
deferIntercept: true, // Allows APP_INITIALIZER to complete before routing
useHash: true,
}),
],
declarations: [
/* Component declarations ... */
],
providers: [
AppConfig, {
provide: APP_INITIALIZER,
useFactory: initResources,
deps: [AppConfig, TranslationConfigModule, UIRouter],
multi: true,
},
],
bootstrap: [AppComponent],
})
^ This part prevents the routes from initializing.
It is then necessary to call listen()
and sync()
to resume the router:
export function initResources(config: AppConfig, translate: TranslationConfigModule, uiRouter: UIRouter) {
const router = uiRouter;
return () => config.load(translate).then(() => {
/*
Recover from `deferIntercept: true` in UIRouterModule
import below. (Allows Ng APP_INITIALIZER to finish before
routing begins.)
*/
router.urlRouter.listen();
router.urlRouter.sync();
});
}
Upvotes: 4