/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/router/src/router_module.ts
262 строки
9 KB
Jordan Webster
feat(router): Add `options` optional parameter for `withComponentInputBinding`
13 мар 2026, 01:36
13 мар 2026, 01:36
89c9a4d
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import { HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, ViewportScroller, } from '@angular/common'; import { APP_BOOTSTRAP_LISTENER, ComponentRef, inject, InjectionToken, ModuleWithProviders, NgModule, Provider, ɵRuntimeError as RuntimeError, } from '@angular/core'; import {EmptyOutletComponent} from './components/empty_outlet'; import {RouterLink} from './directives/router_link'; import {RouterLinkActive} from './directives/router_link_active'; import {RouterOutlet} from './directives/router_outlet'; import {RuntimeErrorCode} from './errors'; import {Routes} from './models'; import {NAVIGATION_ERROR_HANDLER} from './navigation_transition'; import { getBootstrapListener, rootRoute, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withPreloading, withViewTransitions, } from './provide_router'; import {Router} from './router'; import {ExtraOptions, ROUTER_CONFIGURATION} from './router_config'; import {RouterConfigLoader, ROUTES} from './router_config_loader'; import {ChildrenOutletContexts} from './router_outlet_context'; import {ROUTER_SCROLLER, RouterScroller} from './router_scroller'; import {ActivatedRoute} from './router_state'; import {DefaultUrlSerializer, UrlSerializer} from './url_tree'; /** * The directives defined in the `RouterModule`. */ const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkActive, EmptyOutletComponent]; /** * @docsNotRequired */ export const ROUTER_FORROOT_GUARD = new InjectionToken<void>( typeof ngDevMode === 'undefined' || ngDevMode ? 'router duplicate forRoot guard' : '', ); // TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept // here to avoid a breaking change whereby the provider order matters based on where the // `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a "breaking" // change in a major version. export const ROUTER_PROVIDERS: Provider[] = [ Location, {provide: UrlSerializer, useClass: DefaultUrlSerializer}, Router, ChildrenOutletContexts, {provide: ActivatedRoute, useFactory: rootRoute}, RouterConfigLoader, ]; /** * @description * * Adds directives and providers for in-app navigation among views defined in an application. * Use the Angular `Router` service to declaratively specify application states and manage state * transitions. * * You can import this NgModule multiple times, once for each lazy-loaded bundle. * However, only one `Router` service can be active. * To ensure this, there are two ways to register routes when importing this module: * * * The `forRoot()` method creates an `NgModule` that contains all the directives, the given * routes, and the `Router` service itself. * * The `forChild()` method creates an `NgModule` that contains all the directives and the given * routes, but does not include the `Router` service. * * @see [Routing and Navigation guide](guide/routing/common-router-tasks) for an * overview of how the `Router` service should be used. * * @publicApi */ @NgModule({ imports: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES, }) export class RouterModule { constructor() { if (typeof ngDevMode === 'undefined' || ngDevMode) { inject(ROUTER_FORROOT_GUARD, {optional: true}); } } /** * Creates and configures a module with all the router providers and directives. * Optionally sets up an application listener to perform an initial navigation. * * When registering the NgModule at the root, import as follows: * * ```ts * @NgModule({ * imports: [RouterModule.forRoot(ROUTES)] * }) * class MyNgModule {} * ``` * * @param routes An array of `Route` objects that define the navigation paths for the application. * @param config An `ExtraOptions` configuration object that controls how navigation is performed. * @return The new `NgModule`. * */ static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders<RouterModule> { return { ngModule: RouterModule, providers: [ ROUTER_PROVIDERS, typeof ngDevMode === 'undefined' || ngDevMode ? config?.enableTracing ? withDebugTracing().ɵproviders : [] : [], {provide: ROUTES, multi: true, useValue: routes}, typeof ngDevMode === 'undefined' || ngDevMode ? { provide: ROUTER_FORROOT_GUARD, useFactory: provideForRootGuard, } : [], config?.errorHandler ? { provide: NAVIGATION_ERROR_HANDLER, useValue: config.errorHandler, } : [], {provide: ROUTER_CONFIGURATION, useValue: config ? config : {}}, config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(), provideRouterScroller(), config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [], config?.initialNavigation ? provideInitialNavigation(config) : [], config?.bindToComponentInputs ? withComponentInputBinding( typeof config.bindToComponentInputs === 'object' ? config.bindToComponentInputs : {}, ).ɵproviders : [], config?.enableViewTransitions ? withViewTransitions().ɵproviders : [], provideRouterInitializer(), ], }; } /** * Creates a module with all the router directives and a provider registering routes, * without creating a new Router service. * When registering for submodules and lazy-loaded submodules, create the NgModule as follows: * * ```ts * @NgModule({ * imports: [RouterModule.forChild(ROUTES)] * }) * class MyNgModule {} * ``` * * @param routes An array of `Route` objects that define the navigation paths for the submodule. * @return The new NgModule. * */ static forChild(routes: Routes): ModuleWithProviders<RouterModule> { return { ngModule: RouterModule, providers: [{provide: ROUTES, multi: true, useValue: routes}], }; } } /** * For internal use by `RouterModule` only. Note that this differs from `withInMemoryRouterScroller` * because it reads from the `ExtraOptions` which should not be used in the standalone world. */ export function provideRouterScroller(): Provider { return { provide: ROUTER_SCROLLER, useFactory: () => { const viewportScroller = inject(ViewportScroller); const config: ExtraOptions = inject(ROUTER_CONFIGURATION); if (config.scrollOffset) { viewportScroller.setOffset(config.scrollOffset); } return new RouterScroller(config); }, }; } // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` should // provide hash location directly via `{provide: LocationStrategy, useClass: HashLocationStrategy}`. function provideHashLocationStrategy(): Provider { return {provide: LocationStrategy, useClass: HashLocationStrategy}; } // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` does not // need this at all because `PathLocationStrategy` is the default factory for `LocationStrategy`. function providePathLocationStrategy(): Provider { return {provide: LocationStrategy, useClass: PathLocationStrategy}; } export function provideForRootGuard(): any { const router = inject(Router, {optional: true, skipSelf: true}); if (router) { throw new RuntimeError( RuntimeErrorCode.FOR_ROOT_CALLED_TWICE, `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` + ` Lazy loaded modules should use RouterModule.forChild() instead.`, ); } return 'guarded'; } // Note: For internal use only with `RouterModule`. Standalone router setup with `provideRouter` // users call `withXInitialNavigation` directly. function provideInitialNavigation(config: Pick<ExtraOptions, 'initialNavigation'>): Provider[] { return [ config.initialNavigation === 'disabled' ? withDisabledInitialNavigation().ɵproviders : [], config.initialNavigation === 'enabledBlocking' ? withEnabledBlockingInitialNavigation().ɵproviders : [], ]; } // TODO(atscott): This should not be in the public API /** * A DI token for the router initializer that * is called after the app is bootstrapped. * * @publicApi */ export const ROUTER_INITIALIZER = new InjectionToken<(compRef: ComponentRef<any>) => void>( typeof ngDevMode === 'undefined' || ngDevMode ? 'Router Initializer' : '', ); function provideRouterInitializer(): Provider[] { return [ // ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER. {provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener}, {provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER}, ]; }