mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-16 14:33:03 +00:00
93219: Support Router in InitService
For Router to work properly, APP_BASE_HREF must be resolved _before_ the APP_INITIALIZER factory is called (otherwise Angular will attempt to initialize APP_BASE_HREF too soon) To fix this we add a pre-initialization hook to APP_CONFIG so BrowserInitService can resolve it before APP_INITIALIZER
This commit is contained in:
@@ -6,30 +6,18 @@
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from './app.reducer';
|
||||
import { CheckAuthenticationTokenAction } from './core/auth/auth.actions';
|
||||
import { CorrelationIdService } from './correlation-id/correlation-id.service';
|
||||
import { DSpaceTransferState } from '../modules/transfer-state/dspace-transfer-state.service';
|
||||
import { APP_INITIALIZER, Provider, Type } from '@angular/core';
|
||||
import { TransferState } from '@angular/platform-browser';
|
||||
import { APP_CONFIG } from '../config/app-config.interface';
|
||||
import { environment } from '../environments/environment';
|
||||
import { AppState } from './app.reducer';
|
||||
|
||||
/**
|
||||
* Performs the initialization of the app.
|
||||
*
|
||||
* Should have distinct extensions for server & browser for the specifics.
|
||||
* Should be provided in AppModule as follows
|
||||
* ```
|
||||
* {
|
||||
* provide: APP_INITIALIZER
|
||||
* useFactory: (initService: InitService) => initService.init(),
|
||||
* deps: [ InitService ],
|
||||
* multi: true,
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In order to be injected in the common APP_INITIALIZER,
|
||||
* concrete subclasses should be provided in their respective app modules as
|
||||
* ```
|
||||
* { provide: InitService, useClass: SpecificInitService }
|
||||
* ```
|
||||
* Should be extended to implement server- & browser-specific functionality.
|
||||
*/
|
||||
export abstract class InitService {
|
||||
protected constructor(
|
||||
@@ -40,14 +28,63 @@ export abstract class InitService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main initialization method, to be used as the APP_INITIALIZER factory.
|
||||
*
|
||||
* Note that the body of this method and the callback it returns are called
|
||||
* at different times.
|
||||
* This is important to take into account when other providers depend on the
|
||||
* initialization logic (e.g. APP_BASE_HREF)
|
||||
* The initialization providers to use in `*AppModule`
|
||||
* - this concrete {@link InitService}
|
||||
* - {@link APP_CONFIG} with optional pre-initialization hook
|
||||
* - {@link APP_INITIALIZER}
|
||||
* <br>
|
||||
* Should only be called on concrete subclasses of InitService for the initialization hooks to work
|
||||
*/
|
||||
abstract init(): () => Promise<boolean>;
|
||||
public static providers(): Provider[] {
|
||||
if (!InitService.isPrototypeOf(this)) {
|
||||
throw new Error(
|
||||
'Initalization providers should only be generated from concrete subclasses of InitService'
|
||||
);
|
||||
}
|
||||
return [
|
||||
{
|
||||
provide: InitService,
|
||||
useClass: this as unknown as Type<InitService>,
|
||||
},
|
||||
{
|
||||
provide: APP_CONFIG,
|
||||
useFactory: (transferState: TransferState) => {
|
||||
this.resolveAppConfig(transferState);
|
||||
return environment;
|
||||
},
|
||||
deps: [ TransferState ]
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: (initService: InitService) => initService.init(),
|
||||
deps: [ InitService ],
|
||||
multi: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional pre-initialization method to ensure that {@link APP_CONFIG} is fully resolved before {@link init} is called.
|
||||
*
|
||||
* For example, Router depends on APP_BASE_HREF, which in turn depends on APP_CONFIG.
|
||||
* In production mode, APP_CONFIG is resolved from the TransferState when the app is initialized.
|
||||
* If we want to use Router within APP_INITIALIZER, we have to make sure APP_BASE_HREF is resolved beforehand.
|
||||
* In this case that means that we must transfer the configuration from the SSR state during pre-initialization.
|
||||
* @protected
|
||||
*/
|
||||
protected static resolveAppConfig(
|
||||
transferState: TransferState
|
||||
): void {
|
||||
// overriden in subclasses if applicable
|
||||
}
|
||||
|
||||
/**
|
||||
* Main initialization method.
|
||||
* @protected
|
||||
*/
|
||||
protected abstract init(): () => Promise<boolean>;
|
||||
|
||||
// Common initialization steps
|
||||
|
||||
protected checkAuthenticationToken(): void {
|
||||
this.store.dispatch(new CheckAuthenticationTokenAction());
|
||||
|
Reference in New Issue
Block a user