Skip to content

Commit

Permalink
refactor(router): Update Router to be providedIn: 'root' (#46824)
Browse files Browse the repository at this point in the history
This commit updates the Router itself to be `providedIn: 'root'` with a
factory function rather than provided in the `RouterModule`.

PR Close #46824
  • Loading branch information
atscott authored and AndrewKushnir committed Jul 20, 2022
1 parent a0b2d36 commit d583f85
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 338 deletions.
4 changes: 2 additions & 2 deletions goldens/public-api/router/index.md
Expand Up @@ -737,11 +737,11 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {

// @public
export class RouterModule {
constructor(guard: any, router: Router);
constructor(guard: any);
static forChild(routes: Routes): ModuleWithProviders<RouterModule>;
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders<RouterModule>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<RouterModule, [{ optional: true; }, { optional: true; }]>;
static ɵfac: i0.ɵɵFactoryDeclaration<RouterModule, [{ optional: true; }]>;
// (undocumented)
static ɵinj: i0.ɵɵInjectorDeclaration<RouterModule>;
// (undocumented)
Expand Down
3 changes: 3 additions & 0 deletions packages/core/test/bundling/router/bundle.golden_symbols.json
Expand Up @@ -1838,6 +1838,9 @@
{
"name": "setUpAttributes"
},
{
"name": "setupRouter"
},
{
"name": "shallowEqual"
},
Expand Down
3 changes: 2 additions & 1 deletion packages/router/src/index.ts
Expand Up @@ -16,8 +16,9 @@ export {CanActivate, CanActivateChild, CanDeactivate, CanLoad, CanMatch, CanMatc
export {DefaultTitleStrategy, TitleStrategy} from './page_title_strategy';
export {BaseRouteReuseStrategy, DetachedRouteHandle, RouteReuseStrategy} from './route_reuse_strategy';
export {Navigation, NavigationExtras, Router, UrlCreationOptions} from './router';
export {ExtraOptions, InitialNavigation, ROUTER_CONFIGURATION} from './router_config';
export {ROUTES} from './router_config_loader';
export {ExtraOptions, InitialNavigation, provideRoutes, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, RouterModule} from './router_module';
export {provideRoutes, ROUTER_INITIALIZER, RouterModule} from './router_module';
export {ChildrenOutletContexts, OutletContext} from './router_outlet_context';
export {NoPreloading, PreloadAllModules, PreloadingStrategy, RouterPreloader} from './router_preloader';
export {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot} from './router_state';
Expand Down
4 changes: 2 additions & 2 deletions packages/router/src/private_export.ts
Expand Up @@ -8,6 +8,6 @@


export {ɵEmptyOutletComponent} from './components/empty_outlet';
export {RestoredState as ɵRestoredState} from './router';
export {assignExtraOptionsToRouter as ɵassignExtraOptionsToRouter, providePreloading as ɵprovidePreloading, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS} from './router_module';
export {assignExtraOptionsToRouter as ɵassignExtraOptionsToRouter, RestoredState as ɵRestoredState} from './router';
export {providePreloading as ɵprovidePreloading, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS} from './router_module';
export {flatten as ɵflatten} from './utils/collection';
84 changes: 69 additions & 15 deletions packages/router/src/router.ts
Expand Up @@ -7,7 +7,7 @@
*/

import {Location} from '@angular/common';
import {Compiler, Injectable, Injector, NgModuleRef, NgZone, Type, ɵConsole as Console, ɵRuntimeError as RuntimeError} from '@angular/core';
import {Compiler, inject, Injectable, Injector, NgModuleRef, NgZone, Type, ɵConsole as Console, ɵRuntimeError as RuntimeError} from '@angular/core';
import {BehaviorSubject, combineLatest, EMPTY, Observable, of, Subject, SubscriptionLike} from 'rxjs';
import {catchError, defaultIfEmpty, filter, finalize, map, switchMap, take, tap} from 'rxjs/operators';

Expand All @@ -23,14 +23,16 @@ import {checkGuards} from './operators/check_guards';
import {recognize} from './operators/recognize';
import {resolveData} from './operators/resolve_data';
import {switchTap} from './operators/switch_tap';
import {TitleStrategy} from './page_title_strategy';
import {DefaultTitleStrategy, TitleStrategy} from './page_title_strategy';
import {DefaultRouteReuseStrategy, RouteReuseStrategy} from './route_reuse_strategy';
import {RouterConfigLoader} from './router_config_loader';
import {ErrorHandler, ExtraOptions, ROUTER_CONFIGURATION} from './router_config';
import {RouterConfigLoader, ROUTES} from './router_config_loader';
import {ChildrenOutletContexts} from './router_outlet_context';
import {ActivatedRoute, ActivatedRouteSnapshot, createEmptyState, RouterState, RouterStateSnapshot} from './router_state';
import {Params} from './shared';
import {DefaultUrlHandlingStrategy, UrlHandlingStrategy} from './url_handling_strategy';
import {containsTree, createEmptyUrlTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree';
import {flatten} from './utils/collection';
import {standardizeConfig, validateConfig} from './utils/config';
import {Checks, getAllRouteGuards} from './utils/preactivation';

Expand Down Expand Up @@ -163,17 +165,6 @@ export interface UrlCreationOptions {
*/
export interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {}

/**
* Error handler that is invoked when a navigation error occurs.
*
* If the handler returns a value, the navigation Promise is resolved with this value.
* If the handler throws an exception, the navigation Promise is rejected with
* the exception.
*
* @publicApi
*/
export type ErrorHandler = (error: any) => any;

function defaultErrorHandler(error: any): any {
throw error;
}
Expand Down Expand Up @@ -301,6 +292,66 @@ export const subsetMatchOptions: IsActiveMatchOptions = {
queryParams: 'subset'
};

export function assignExtraOptionsToRouter(opts: ExtraOptions, router: Router): void {
if (opts.errorHandler) {
router.errorHandler = opts.errorHandler;
}

if (opts.malformedUriErrorHandler) {
router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
}

if (opts.onSameUrlNavigation) {
router.onSameUrlNavigation = opts.onSameUrlNavigation;
}

if (opts.paramsInheritanceStrategy) {
router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
}

if (opts.relativeLinkResolution) {
router.relativeLinkResolution = opts.relativeLinkResolution;
}

if (opts.urlUpdateStrategy) {
router.urlUpdateStrategy = opts.urlUpdateStrategy;
}

if (opts.canceledNavigationResolution) {
router.canceledNavigationResolution = opts.canceledNavigationResolution;
}
}

export function setupRouter() {
const urlSerializer = inject(UrlSerializer);
const contexts = inject(ChildrenOutletContexts);
const location = inject(Location);
const injector = inject(Injector);
const compiler = inject(Compiler);
const config = inject(ROUTES, {optional: true}) ?? [];
const opts = inject(ROUTER_CONFIGURATION, {optional: true}) ?? {};
const defaultTitleStrategy = inject(DefaultTitleStrategy);
const titleStrategy = inject(TitleStrategy, {optional: true});
const urlHandlingStrategy = inject(UrlHandlingStrategy, {optional: true});
const routeReuseStrategy = inject(RouteReuseStrategy, {optional: true});
const router =
new Router(null, urlSerializer, contexts, location, injector, compiler, flatten(config));

if (urlHandlingStrategy) {
router.urlHandlingStrategy = urlHandlingStrategy;
}

if (routeReuseStrategy) {
router.routeReuseStrategy = routeReuseStrategy;
}

router.titleStrategy = titleStrategy ?? defaultTitleStrategy;

assignExtraOptionsToRouter(opts, router);

return router;
}

/**
* @description
*
Expand All @@ -313,7 +364,10 @@ export const subsetMatchOptions: IsActiveMatchOptions = {
*
* @publicApi
*/
@Injectable()
@Injectable({
providedIn: 'root',
useFactory: setupRouter,
})
export class Router {
/**
* Represents the activated `UrlTree` that the `Router` is configured to handle (through
Expand Down

0 comments on commit d583f85

Please sign in to comment.