feat(router): throw a helpful error when misusing forRoot() from a lazy module. (#10996)
This commit is contained in:
parent
c02325dd06
commit
5ddecb18a7
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {APP_BASE_HREF, HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
|
import {APP_BASE_HREF, HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
|
||||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, ApplicationRef, Compiler, Inject, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, OpaqueToken, Optional, SystemJsNgModuleLoader} from '@angular/core';
|
import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, ApplicationRef, BaseException, Compiler, Inject, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, OpaqueToken, Optional, SkipSelf, SystemJsNgModuleLoader} from '@angular/core';
|
||||||
|
|
||||||
import {Route, Routes} from './config';
|
import {Route, Routes} from './config';
|
||||||
import {RouterLink, RouterLinkWithHref} from './directives/router_link';
|
import {RouterLink, RouterLinkWithHref} from './directives/router_link';
|
||||||
@ -32,6 +32,8 @@ export const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref,
|
|||||||
*/
|
*/
|
||||||
export const ROUTER_CONFIGURATION = new OpaqueToken('ROUTER_CONFIGURATION');
|
export const ROUTER_CONFIGURATION = new OpaqueToken('ROUTER_CONFIGURATION');
|
||||||
|
|
||||||
|
export const ROUTER_FORROOT_GUARD = new OpaqueToken('ROUTER_FORROOT_GUARD');
|
||||||
|
|
||||||
const pathLocationStrategy = {
|
const pathLocationStrategy = {
|
||||||
provide: LocationStrategy,
|
provide: LocationStrategy,
|
||||||
useClass: PathLocationStrategy
|
useClass: PathLocationStrategy
|
||||||
@ -81,11 +83,17 @@ export const ROUTER_PROVIDERS: any[] = [
|
|||||||
*/
|
*/
|
||||||
@NgModule({declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES})
|
@NgModule({declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES})
|
||||||
export class RouterModule {
|
export class RouterModule {
|
||||||
|
constructor(@Optional() @Inject(ROUTER_FORROOT_GUARD) guard: any) {}
|
||||||
|
|
||||||
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders {
|
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders {
|
||||||
return {
|
return {
|
||||||
ngModule: RouterModule,
|
ngModule: RouterModule,
|
||||||
providers: [
|
providers: [
|
||||||
ROUTER_PROVIDERS, provideRoutes(routes),
|
ROUTER_PROVIDERS, provideRoutes(routes), {
|
||||||
|
provide: ROUTER_FORROOT_GUARD,
|
||||||
|
useFactory: provideForRootGuard,
|
||||||
|
deps: [[Router, new Optional(), new SkipSelf()]]
|
||||||
|
},
|
||||||
{provide: ROUTER_CONFIGURATION, useValue: config ? config : {}}, {
|
{provide: ROUTER_CONFIGURATION, useValue: config ? config : {}}, {
|
||||||
provide: LocationStrategy,
|
provide: LocationStrategy,
|
||||||
useFactory: provideLocationStrategy,
|
useFactory: provideLocationStrategy,
|
||||||
@ -109,6 +117,14 @@ export function provideLocationStrategy(
|
|||||||
new PathLocationStrategy(platformLocationStrategy, baseHref);
|
new PathLocationStrategy(platformLocationStrategy, baseHref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function provideForRootGuard(router: Router): any {
|
||||||
|
if (router) {
|
||||||
|
throw new BaseException(
|
||||||
|
`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`);
|
||||||
|
}
|
||||||
|
return 'guarded';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
|
@ -1411,7 +1411,34 @@ describe('Integration', () => {
|
|||||||
expect(fixture.debugElement.nativeElement)
|
expect(fixture.debugElement.nativeElement)
|
||||||
.toHaveText('lazy-loaded-parent [lazy-loaded-child]');
|
.toHaveText('lazy-loaded-parent [lazy-loaded-child]');
|
||||||
})));
|
})));
|
||||||
|
it('throws an error when forRoot() is used in a lazy context',
|
||||||
|
fakeAsync(inject(
|
||||||
|
[Router, Location, NgModuleFactoryLoader],
|
||||||
|
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||||
|
@Component({selector: 'lazy', template: 'should not show'})
|
||||||
|
class LazyLoadedComponent {
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [LazyLoadedComponent],
|
||||||
|
imports: [RouterModule.forRoot([{path: 'loaded', component: LazyLoadedComponent}])]
|
||||||
|
})
|
||||||
|
class LoadedModule {
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.stubbedModules = {expected: LoadedModule};
|
||||||
|
|
||||||
|
const fixture = createRoot(router, RootCmp);
|
||||||
|
|
||||||
|
router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]);
|
||||||
|
|
||||||
|
let recordedError: any = null;
|
||||||
|
router.navigateByUrl('/lazy/loaded').catch(err => recordedError = err);
|
||||||
|
advance(fixture);
|
||||||
|
expect(recordedError.message)
|
||||||
|
.toEqual(
|
||||||
|
`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`);
|
||||||
|
})));
|
||||||
it('should combine routes from multiple modules into a single configuration',
|
it('should combine routes from multiple modules into a single configuration',
|
||||||
fakeAsync(inject(
|
fakeAsync(inject(
|
||||||
[Router, Location, NgModuleFactoryLoader],
|
[Router, Location, NgModuleFactoryLoader],
|
||||||
|
1
tools/public_api_guard/router/index.d.ts
vendored
1
tools/public_api_guard/router/index.d.ts
vendored
@ -239,6 +239,7 @@ export declare class RouterLinkWithHref implements OnChanges, OnDestroy {
|
|||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
export declare class RouterModule {
|
export declare class RouterModule {
|
||||||
|
constructor(guard: any);
|
||||||
static forChild(routes: Routes): ModuleWithProviders;
|
static forChild(routes: Routes): ModuleWithProviders;
|
||||||
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders;
|
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user