router_module-DTJgGWLd.mjs 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  1. /**
  2. * @license Angular v19.2.13
  3. * (c) 2010-2025 Google LLC. https://angular.io/
  4. * License: MIT
  5. */
  6. import * as i3 from '@angular/common';
  7. import { LOCATION_INITIALIZED, HashLocationStrategy, LocationStrategy, ViewportScroller, Location, PathLocationStrategy } from '@angular/common';
  8. import * as i0 from '@angular/core';
  9. import { ɵRuntimeError as _RuntimeError, ɵɵsanitizeUrlOrResourceUrl as __sanitizeUrlOrResourceUrl, booleanAttribute, HostListener, Input, HostBinding, Attribute, Directive, EventEmitter, Output, ContentChildren, Optional, createEnvironmentInjector, Injectable, InjectionToken, ɵperformanceMarkFeature as _performanceMarkFeature, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, provideAppInitializer, inject, Injector, ApplicationRef, InjectFlags, NgZone, SkipSelf, NgModule } from '@angular/core';
  10. import { NavigationEnd, isUrlTree, Router, ActivatedRoute, RouterConfigLoader, NavigationStart, NavigationSkipped, NavigationSkippedCode, Scroll, UrlSerializer, NavigationTransitions, ROUTES, afterNextNavigation, ROUTER_CONFIGURATION, NAVIGATION_ERROR_HANDLER, RoutedComponentInputBinder, INPUT_BINDER, createViewTransition, CREATE_VIEW_TRANSITION, VIEW_TRANSITION_OPTIONS, stringifyEvent, DefaultUrlSerializer, ChildrenOutletContexts, RouterOutlet, ɵEmptyOutletComponent as _EmptyOutletComponent } from './router-Dwfin5Au.mjs';
  11. import { Subject, of, from } from 'rxjs';
  12. import { mergeAll, catchError, filter, concatMap, mergeMap } from 'rxjs/operators';
  13. /**
  14. * @description
  15. *
  16. * When applied to an element in a template, makes that element a link
  17. * that initiates navigation to a route. Navigation opens one or more routed components
  18. * in one or more `<router-outlet>` locations on the page.
  19. *
  20. * Given a route configuration `[{ path: 'user/:name', component: UserCmp }]`,
  21. * the following creates a static link to the route:
  22. * `<a routerLink="/user/bob">link to user component</a>`
  23. *
  24. * You can use dynamic values to generate the link.
  25. * For a dynamic link, pass an array of path segments,
  26. * followed by the params for each segment.
  27. * For example, `['/team', teamId, 'user', userName, {details: true}]`
  28. * generates a link to `/team/11/user/bob;details=true`.
  29. *
  30. * Multiple static segments can be merged into one term and combined with dynamic segments.
  31. * For example, `['/team/11/user', userName, {details: true}]`
  32. *
  33. * The input that you provide to the link is treated as a delta to the current URL.
  34. * For instance, suppose the current URL is `/user/(box//aux:team)`.
  35. * The link `<a [routerLink]="['/user/jim']">Jim</a>` creates the URL
  36. * `/user/(jim//aux:team)`.
  37. * See {@link Router#createUrlTree} for more information.
  38. *
  39. * @usageNotes
  40. *
  41. * You can use absolute or relative paths in a link, set query parameters,
  42. * control how parameters are handled, and keep a history of navigation states.
  43. *
  44. * ### Relative link paths
  45. *
  46. * The first segment name can be prepended with `/`, `./`, or `../`.
  47. * * If the first segment begins with `/`, the router looks up the route from the root of the
  48. * app.
  49. * * If the first segment begins with `./`, or doesn't begin with a slash, the router
  50. * looks in the children of the current activated route.
  51. * * If the first segment begins with `../`, the router goes up one level in the route tree.
  52. *
  53. * ### Setting and handling query params and fragments
  54. *
  55. * The following link adds a query parameter and a fragment to the generated URL:
  56. *
  57. * ```html
  58. * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
  59. * link to user component
  60. * </a>
  61. * ```
  62. * By default, the directive constructs the new URL using the given query parameters.
  63. * The example generates the link: `/user/bob?debug=true#education`.
  64. *
  65. * You can instruct the directive to handle query parameters differently
  66. * by specifying the `queryParamsHandling` option in the link.
  67. * Allowed values are:
  68. *
  69. * - `'merge'`: Merge the given `queryParams` into the current query params.
  70. * - `'preserve'`: Preserve the current query params.
  71. *
  72. * For example:
  73. *
  74. * ```html
  75. * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
  76. * link to user component
  77. * </a>
  78. * ```
  79. *
  80. * `queryParams`, `fragment`, `queryParamsHandling`, `preserveFragment`, and `relativeTo`
  81. * cannot be used when the `routerLink` input is a `UrlTree`.
  82. *
  83. * See {@link UrlCreationOptions#queryParamsHandling}.
  84. *
  85. * ### Preserving navigation history
  86. *
  87. * You can provide a `state` value to be persisted to the browser's
  88. * [`History.state` property](https://developer.mozilla.org/en-US/docs/Web/API/History#Properties).
  89. * For example:
  90. *
  91. * ```html
  92. * <a [routerLink]="['/user/bob']" [state]="{tracingId: 123}">
  93. * link to user component
  94. * </a>
  95. * ```
  96. *
  97. * Use {@link Router#getCurrentNavigation} to retrieve a saved
  98. * navigation-state value. For example, to capture the `tracingId` during the `NavigationStart`
  99. * event:
  100. *
  101. * ```ts
  102. * // Get NavigationStart events
  103. * router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => {
  104. * const navigation = router.getCurrentNavigation();
  105. * tracingService.trace({id: navigation.extras.state.tracingId});
  106. * });
  107. * ```
  108. *
  109. * @ngModule RouterModule
  110. *
  111. * @publicApi
  112. */
  113. class RouterLink {
  114. router;
  115. route;
  116. tabIndexAttribute;
  117. renderer;
  118. el;
  119. locationStrategy;
  120. /**
  121. * Represents an `href` attribute value applied to a host element,
  122. * when a host element is `<a>`. For other tags, the value is `null`.
  123. */
  124. href = null;
  125. /**
  126. * Represents the `target` attribute on a host element.
  127. * This is only used when the host element is an `<a>` tag.
  128. */
  129. target;
  130. /**
  131. * Passed to {@link Router#createUrlTree} as part of the
  132. * `UrlCreationOptions`.
  133. * @see {@link UrlCreationOptions#queryParams}
  134. * @see {@link Router#createUrlTree}
  135. */
  136. queryParams;
  137. /**
  138. * Passed to {@link Router#createUrlTree} as part of the
  139. * `UrlCreationOptions`.
  140. * @see {@link UrlCreationOptions#fragment}
  141. * @see {@link Router#createUrlTree}
  142. */
  143. fragment;
  144. /**
  145. * Passed to {@link Router#createUrlTree} as part of the
  146. * `UrlCreationOptions`.
  147. * @see {@link UrlCreationOptions#queryParamsHandling}
  148. * @see {@link Router#createUrlTree}
  149. */
  150. queryParamsHandling;
  151. /**
  152. * Passed to {@link Router#navigateByUrl} as part of the
  153. * `NavigationBehaviorOptions`.
  154. * @see {@link NavigationBehaviorOptions#state}
  155. * @see {@link Router#navigateByUrl}
  156. */
  157. state;
  158. /**
  159. * Passed to {@link Router#navigateByUrl} as part of the
  160. * `NavigationBehaviorOptions`.
  161. * @see {@link NavigationBehaviorOptions#info}
  162. * @see {@link Router#navigateByUrl}
  163. */
  164. info;
  165. /**
  166. * Passed to {@link Router#createUrlTree} as part of the
  167. * `UrlCreationOptions`.
  168. * Specify a value here when you do not want to use the default value
  169. * for `routerLink`, which is the current activated route.
  170. * Note that a value of `undefined` here will use the `routerLink` default.
  171. * @see {@link UrlCreationOptions#relativeTo}
  172. * @see {@link Router#createUrlTree}
  173. */
  174. relativeTo;
  175. /** Whether a host element is an `<a>` tag. */
  176. isAnchorElement;
  177. subscription;
  178. /** @internal */
  179. onChanges = new Subject();
  180. constructor(router, route, tabIndexAttribute, renderer, el, locationStrategy) {
  181. this.router = router;
  182. this.route = route;
  183. this.tabIndexAttribute = tabIndexAttribute;
  184. this.renderer = renderer;
  185. this.el = el;
  186. this.locationStrategy = locationStrategy;
  187. const tagName = el.nativeElement.tagName?.toLowerCase();
  188. this.isAnchorElement = tagName === 'a' || tagName === 'area';
  189. if (this.isAnchorElement) {
  190. this.subscription = router.events.subscribe((s) => {
  191. if (s instanceof NavigationEnd) {
  192. this.updateHref();
  193. }
  194. });
  195. }
  196. else {
  197. this.setTabIndexIfNotOnNativeEl('0');
  198. }
  199. }
  200. /**
  201. * Passed to {@link Router#createUrlTree} as part of the
  202. * `UrlCreationOptions`.
  203. * @see {@link UrlCreationOptions#preserveFragment}
  204. * @see {@link Router#createUrlTree}
  205. */
  206. preserveFragment = false;
  207. /**
  208. * Passed to {@link Router#navigateByUrl} as part of the
  209. * `NavigationBehaviorOptions`.
  210. * @see {@link NavigationBehaviorOptions#skipLocationChange}
  211. * @see {@link Router#navigateByUrl}
  212. */
  213. skipLocationChange = false;
  214. /**
  215. * Passed to {@link Router#navigateByUrl} as part of the
  216. * `NavigationBehaviorOptions`.
  217. * @see {@link NavigationBehaviorOptions#replaceUrl}
  218. * @see {@link Router#navigateByUrl}
  219. */
  220. replaceUrl = false;
  221. /**
  222. * Modifies the tab index if there was not a tabindex attribute on the element during
  223. * instantiation.
  224. */
  225. setTabIndexIfNotOnNativeEl(newTabIndex) {
  226. if (this.tabIndexAttribute != null /* both `null` and `undefined` */ || this.isAnchorElement) {
  227. return;
  228. }
  229. this.applyAttributeValue('tabindex', newTabIndex);
  230. }
  231. /** @docs-private */
  232. // TODO(atscott): Remove changes parameter in major version as a breaking change.
  233. ngOnChanges(changes) {
  234. if (ngDevMode &&
  235. isUrlTree(this.routerLinkInput) &&
  236. (this.fragment !== undefined ||
  237. this.queryParams ||
  238. this.queryParamsHandling ||
  239. this.preserveFragment ||
  240. this.relativeTo)) {
  241. throw new _RuntimeError(4016 /* RuntimeErrorCode.INVALID_ROUTER_LINK_INPUTS */, 'Cannot configure queryParams or fragment when using a UrlTree as the routerLink input value.');
  242. }
  243. if (this.isAnchorElement) {
  244. this.updateHref();
  245. }
  246. // This is subscribed to by `RouterLinkActive` so that it knows to update when there are changes
  247. // to the RouterLinks it's tracking.
  248. this.onChanges.next(this);
  249. }
  250. routerLinkInput = null;
  251. /**
  252. * Commands to pass to {@link Router#createUrlTree} or a `UrlTree`.
  253. * - **array**: commands to pass to {@link Router#createUrlTree}.
  254. * - **string**: shorthand for array of commands with just the string, i.e. `['/route']`
  255. * - **UrlTree**: a `UrlTree` for this link rather than creating one from the commands
  256. * and other inputs that correspond to properties of `UrlCreationOptions`.
  257. * - **null|undefined**: effectively disables the `routerLink`
  258. * @see {@link Router#createUrlTree}
  259. */
  260. set routerLink(commandsOrUrlTree) {
  261. if (commandsOrUrlTree == null) {
  262. this.routerLinkInput = null;
  263. this.setTabIndexIfNotOnNativeEl(null);
  264. }
  265. else {
  266. if (isUrlTree(commandsOrUrlTree)) {
  267. this.routerLinkInput = commandsOrUrlTree;
  268. }
  269. else {
  270. this.routerLinkInput = Array.isArray(commandsOrUrlTree)
  271. ? commandsOrUrlTree
  272. : [commandsOrUrlTree];
  273. }
  274. this.setTabIndexIfNotOnNativeEl('0');
  275. }
  276. }
  277. /** @docs-private */
  278. onClick(button, ctrlKey, shiftKey, altKey, metaKey) {
  279. const urlTree = this.urlTree;
  280. if (urlTree === null) {
  281. return true;
  282. }
  283. if (this.isAnchorElement) {
  284. if (button !== 0 || ctrlKey || shiftKey || altKey || metaKey) {
  285. return true;
  286. }
  287. if (typeof this.target === 'string' && this.target != '_self') {
  288. return true;
  289. }
  290. }
  291. const extras = {
  292. skipLocationChange: this.skipLocationChange,
  293. replaceUrl: this.replaceUrl,
  294. state: this.state,
  295. info: this.info,
  296. };
  297. this.router.navigateByUrl(urlTree, extras);
  298. // Return `false` for `<a>` elements to prevent default action
  299. // and cancel the native behavior, since the navigation is handled
  300. // by the Router.
  301. return !this.isAnchorElement;
  302. }
  303. /** @docs-private */
  304. ngOnDestroy() {
  305. this.subscription?.unsubscribe();
  306. }
  307. updateHref() {
  308. const urlTree = this.urlTree;
  309. this.href =
  310. urlTree !== null && this.locationStrategy
  311. ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(urlTree))
  312. : null;
  313. const sanitizedValue = this.href === null
  314. ? null
  315. : // This class represents a directive that can be added to both `<a>` elements,
  316. // as well as other elements. As a result, we can't define security context at
  317. // compile time. So the security context is deferred to runtime.
  318. // The `ɵɵsanitizeUrlOrResourceUrl` selects the necessary sanitizer function
  319. // based on the tag and property names. The logic mimics the one from
  320. // `packages/compiler/src/schema/dom_security_schema.ts`, which is used at compile time.
  321. //
  322. // Note: we should investigate whether we can switch to using `@HostBinding('attr.href')`
  323. // instead of applying a value via a renderer, after a final merge of the
  324. // `RouterLinkWithHref` directive.
  325. __sanitizeUrlOrResourceUrl(this.href, this.el.nativeElement.tagName.toLowerCase(), 'href');
  326. this.applyAttributeValue('href', sanitizedValue);
  327. }
  328. applyAttributeValue(attrName, attrValue) {
  329. const renderer = this.renderer;
  330. const nativeElement = this.el.nativeElement;
  331. if (attrValue !== null) {
  332. renderer.setAttribute(nativeElement, attrName, attrValue);
  333. }
  334. else {
  335. renderer.removeAttribute(nativeElement, attrName);
  336. }
  337. }
  338. get urlTree() {
  339. if (this.routerLinkInput === null) {
  340. return null;
  341. }
  342. else if (isUrlTree(this.routerLinkInput)) {
  343. return this.routerLinkInput;
  344. }
  345. return this.router.createUrlTree(this.routerLinkInput, {
  346. // If the `relativeTo` input is not defined, we want to use `this.route` by default.
  347. // Otherwise, we should use the value provided by the user in the input.
  348. relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,
  349. queryParams: this.queryParams,
  350. fragment: this.fragment,
  351. queryParamsHandling: this.queryParamsHandling,
  352. preserveFragment: this.preserveFragment,
  353. });
  354. }
  355. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
  356. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.13", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", info: "info", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 });
  357. }
  358. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterLink, decorators: [{
  359. type: Directive,
  360. args: [{
  361. selector: '[routerLink]',
  362. }]
  363. }], ctorParameters: () => [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
  364. type: Attribute,
  365. args: ['tabindex']
  366. }] }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i3.LocationStrategy }], propDecorators: { target: [{
  367. type: HostBinding,
  368. args: ['attr.target']
  369. }, {
  370. type: Input
  371. }], queryParams: [{
  372. type: Input
  373. }], fragment: [{
  374. type: Input
  375. }], queryParamsHandling: [{
  376. type: Input
  377. }], state: [{
  378. type: Input
  379. }], info: [{
  380. type: Input
  381. }], relativeTo: [{
  382. type: Input
  383. }], preserveFragment: [{
  384. type: Input,
  385. args: [{ transform: booleanAttribute }]
  386. }], skipLocationChange: [{
  387. type: Input,
  388. args: [{ transform: booleanAttribute }]
  389. }], replaceUrl: [{
  390. type: Input,
  391. args: [{ transform: booleanAttribute }]
  392. }], routerLink: [{
  393. type: Input
  394. }], onClick: [{
  395. type: HostListener,
  396. args: ['click', [
  397. '$event.button',
  398. '$event.ctrlKey',
  399. '$event.shiftKey',
  400. '$event.altKey',
  401. '$event.metaKey',
  402. ]]
  403. }] } });
  404. /**
  405. *
  406. * @description
  407. *
  408. * Tracks whether the linked route of an element is currently active, and allows you
  409. * to specify one or more CSS classes to add to the element when the linked route
  410. * is active.
  411. *
  412. * Use this directive to create a visual distinction for elements associated with an active route.
  413. * For example, the following code highlights the word "Bob" when the router
  414. * activates the associated route:
  415. *
  416. * ```html
  417. * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
  418. * ```
  419. *
  420. * Whenever the URL is either '/user' or '/user/bob', the "active-link" class is
  421. * added to the anchor tag. If the URL changes, the class is removed.
  422. *
  423. * You can set more than one class using a space-separated string or an array.
  424. * For example:
  425. *
  426. * ```html
  427. * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
  428. * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
  429. * ```
  430. *
  431. * To add the classes only when the URL matches the link exactly, add the option `exact: true`:
  432. *
  433. * ```html
  434. * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
  435. * true}">Bob</a>
  436. * ```
  437. *
  438. * To directly check the `isActive` status of the link, assign the `RouterLinkActive`
  439. * instance to a template variable.
  440. * For example, the following checks the status without assigning any CSS classes:
  441. *
  442. * ```html
  443. * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
  444. * Bob {{ rla.isActive ? '(already open)' : ''}}
  445. * </a>
  446. * ```
  447. *
  448. * You can apply the `RouterLinkActive` directive to an ancestor of linked elements.
  449. * For example, the following sets the active-link class on the `<div>` parent tag
  450. * when the URL is either '/user/jim' or '/user/bob'.
  451. *
  452. * ```html
  453. * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
  454. * <a routerLink="/user/jim">Jim</a>
  455. * <a routerLink="/user/bob">Bob</a>
  456. * </div>
  457. * ```
  458. *
  459. * The `RouterLinkActive` directive can also be used to set the aria-current attribute
  460. * to provide an alternative distinction for active elements to visually impaired users.
  461. *
  462. * For example, the following code adds the 'active' class to the Home Page link when it is
  463. * indeed active and in such case also sets its aria-current attribute to 'page':
  464. *
  465. * ```html
  466. * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
  467. * ```
  468. *
  469. * @ngModule RouterModule
  470. *
  471. * @publicApi
  472. */
  473. class RouterLinkActive {
  474. router;
  475. element;
  476. renderer;
  477. cdr;
  478. link;
  479. links;
  480. classes = [];
  481. routerEventsSubscription;
  482. linkInputChangesSubscription;
  483. _isActive = false;
  484. get isActive() {
  485. return this._isActive;
  486. }
  487. /**
  488. * Options to configure how to determine if the router link is active.
  489. *
  490. * These options are passed to the `Router.isActive()` function.
  491. *
  492. * @see {@link Router#isActive}
  493. */
  494. routerLinkActiveOptions = { exact: false };
  495. /**
  496. * Aria-current attribute to apply when the router link is active.
  497. *
  498. * Possible values: `'page'` | `'step'` | `'location'` | `'date'` | `'time'` | `true` | `false`.
  499. *
  500. * @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current}
  501. */
  502. ariaCurrentWhenActive;
  503. /**
  504. *
  505. * You can use the output `isActiveChange` to get notified each time the link becomes
  506. * active or inactive.
  507. *
  508. * Emits:
  509. * true -> Route is active
  510. * false -> Route is inactive
  511. *
  512. * ```html
  513. * <a
  514. * routerLink="/user/bob"
  515. * routerLinkActive="active-link"
  516. * (isActiveChange)="this.onRouterLinkActive($event)">Bob</a>
  517. * ```
  518. */
  519. isActiveChange = new EventEmitter();
  520. constructor(router, element, renderer, cdr, link) {
  521. this.router = router;
  522. this.element = element;
  523. this.renderer = renderer;
  524. this.cdr = cdr;
  525. this.link = link;
  526. this.routerEventsSubscription = router.events.subscribe((s) => {
  527. if (s instanceof NavigationEnd) {
  528. this.update();
  529. }
  530. });
  531. }
  532. /** @docs-private */
  533. ngAfterContentInit() {
  534. // `of(null)` is used to force subscribe body to execute once immediately (like `startWith`).
  535. of(this.links.changes, of(null))
  536. .pipe(mergeAll())
  537. .subscribe((_) => {
  538. this.update();
  539. this.subscribeToEachLinkOnChanges();
  540. });
  541. }
  542. subscribeToEachLinkOnChanges() {
  543. this.linkInputChangesSubscription?.unsubscribe();
  544. const allLinkChanges = [...this.links.toArray(), this.link]
  545. .filter((link) => !!link)
  546. .map((link) => link.onChanges);
  547. this.linkInputChangesSubscription = from(allLinkChanges)
  548. .pipe(mergeAll())
  549. .subscribe((link) => {
  550. if (this._isActive !== this.isLinkActive(this.router)(link)) {
  551. this.update();
  552. }
  553. });
  554. }
  555. set routerLinkActive(data) {
  556. const classes = Array.isArray(data) ? data : data.split(' ');
  557. this.classes = classes.filter((c) => !!c);
  558. }
  559. /** @docs-private */
  560. ngOnChanges(changes) {
  561. this.update();
  562. }
  563. /** @docs-private */
  564. ngOnDestroy() {
  565. this.routerEventsSubscription.unsubscribe();
  566. this.linkInputChangesSubscription?.unsubscribe();
  567. }
  568. update() {
  569. if (!this.links || !this.router.navigated)
  570. return;
  571. queueMicrotask(() => {
  572. const hasActiveLinks = this.hasActiveLinks();
  573. this.classes.forEach((c) => {
  574. if (hasActiveLinks) {
  575. this.renderer.addClass(this.element.nativeElement, c);
  576. }
  577. else {
  578. this.renderer.removeClass(this.element.nativeElement, c);
  579. }
  580. });
  581. if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
  582. this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
  583. }
  584. else {
  585. this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
  586. }
  587. // Only emit change if the active state changed.
  588. if (this._isActive !== hasActiveLinks) {
  589. this._isActive = hasActiveLinks;
  590. this.cdr.markForCheck();
  591. // Emit on isActiveChange after classes are updated
  592. this.isActiveChange.emit(hasActiveLinks);
  593. }
  594. });
  595. }
  596. isLinkActive(router) {
  597. const options = isActiveMatchOptions(this.routerLinkActiveOptions)
  598. ? this.routerLinkActiveOptions
  599. : // While the types should disallow `undefined` here, it's possible without strict inputs
  600. this.routerLinkActiveOptions.exact || false;
  601. return (link) => {
  602. const urlTree = link.urlTree;
  603. return urlTree ? router.isActive(urlTree, options) : false;
  604. };
  605. }
  606. hasActiveLinks() {
  607. const isActiveCheckFn = this.isLinkActive(this.router);
  608. return (this.link && isActiveCheckFn(this.link)) || this.links.some(isActiveCheckFn);
  609. }
  610. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
  611. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.13", type: RouterLinkActive, isStandalone: true, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
  612. }
  613. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterLinkActive, decorators: [{
  614. type: Directive,
  615. args: [{
  616. selector: '[routerLinkActive]',
  617. exportAs: 'routerLinkActive',
  618. }]
  619. }], ctorParameters: () => [{ type: Router }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: RouterLink, decorators: [{
  620. type: Optional
  621. }] }], propDecorators: { links: [{
  622. type: ContentChildren,
  623. args: [RouterLink, { descendants: true }]
  624. }], routerLinkActiveOptions: [{
  625. type: Input
  626. }], ariaCurrentWhenActive: [{
  627. type: Input
  628. }], isActiveChange: [{
  629. type: Output
  630. }], routerLinkActive: [{
  631. type: Input
  632. }] } });
  633. /**
  634. * Use instead of `'paths' in options` to be compatible with property renaming
  635. */
  636. function isActiveMatchOptions(options) {
  637. return !!options.paths;
  638. }
  639. /**
  640. * @description
  641. *
  642. * Provides a preloading strategy.
  643. *
  644. * @publicApi
  645. */
  646. class PreloadingStrategy {
  647. }
  648. /**
  649. * @description
  650. *
  651. * Provides a preloading strategy that preloads all modules as quickly as possible.
  652. *
  653. * ```ts
  654. * RouterModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})
  655. * ```
  656. *
  657. * @publicApi
  658. */
  659. class PreloadAllModules {
  660. preload(route, fn) {
  661. return fn().pipe(catchError(() => of(null)));
  662. }
  663. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  664. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
  665. }
  666. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PreloadAllModules, decorators: [{
  667. type: Injectable,
  668. args: [{ providedIn: 'root' }]
  669. }] });
  670. /**
  671. * @description
  672. *
  673. * Provides a preloading strategy that does not preload any modules.
  674. *
  675. * This strategy is enabled by default.
  676. *
  677. * @publicApi
  678. */
  679. class NoPreloading {
  680. preload(route, fn) {
  681. return of(null);
  682. }
  683. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  684. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: NoPreloading, providedIn: 'root' });
  685. }
  686. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: NoPreloading, decorators: [{
  687. type: Injectable,
  688. args: [{ providedIn: 'root' }]
  689. }] });
  690. /**
  691. * The preloader optimistically loads all router configurations to
  692. * make navigations into lazily-loaded sections of the application faster.
  693. *
  694. * The preloader runs in the background. When the router bootstraps, the preloader
  695. * starts listening to all navigation events. After every such event, the preloader
  696. * will check if any configurations can be loaded lazily.
  697. *
  698. * If a route is protected by `canLoad` guards, the preloaded will not load it.
  699. *
  700. * @publicApi
  701. */
  702. class RouterPreloader {
  703. router;
  704. injector;
  705. preloadingStrategy;
  706. loader;
  707. subscription;
  708. constructor(router, injector, preloadingStrategy, loader) {
  709. this.router = router;
  710. this.injector = injector;
  711. this.preloadingStrategy = preloadingStrategy;
  712. this.loader = loader;
  713. }
  714. setUpPreloading() {
  715. this.subscription = this.router.events
  716. .pipe(filter((e) => e instanceof NavigationEnd), concatMap(() => this.preload()))
  717. .subscribe(() => { });
  718. }
  719. preload() {
  720. return this.processRoutes(this.injector, this.router.config);
  721. }
  722. /** @docs-private */
  723. ngOnDestroy() {
  724. if (this.subscription) {
  725. this.subscription.unsubscribe();
  726. }
  727. }
  728. processRoutes(injector, routes) {
  729. const res = [];
  730. for (const route of routes) {
  731. if (route.providers && !route._injector) {
  732. route._injector = createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
  733. }
  734. const injectorForCurrentRoute = route._injector ?? injector;
  735. const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
  736. // Note that `canLoad` is only checked as a condition that prevents `loadChildren` and not
  737. // `loadComponent`. `canLoad` guards only block loading of child routes by design. This
  738. // happens as a consequence of needing to descend into children for route matching immediately
  739. // while component loading is deferred until route activation. Because `canLoad` guards can
  740. // have side effects, we cannot execute them here so we instead skip preloading altogether
  741. // when present. Lastly, it remains to be decided whether `canLoad` should behave this way
  742. // at all. Code splitting and lazy loading is separate from client-side authorization checks
  743. // and should not be used as a security measure to prevent loading of code.
  744. if ((route.loadChildren && !route._loadedRoutes && route.canLoad === undefined) ||
  745. (route.loadComponent && !route._loadedComponent)) {
  746. res.push(this.preloadConfig(injectorForCurrentRoute, route));
  747. }
  748. if (route.children || route._loadedRoutes) {
  749. res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
  750. }
  751. }
  752. return from(res).pipe(mergeAll());
  753. }
  754. preloadConfig(injector, route) {
  755. return this.preloadingStrategy.preload(route, () => {
  756. let loadedChildren$;
  757. if (route.loadChildren && route.canLoad === undefined) {
  758. loadedChildren$ = this.loader.loadChildren(injector, route);
  759. }
  760. else {
  761. loadedChildren$ = of(null);
  762. }
  763. const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
  764. if (config === null) {
  765. return of(void 0);
  766. }
  767. route._loadedRoutes = config.routes;
  768. route._loadedInjector = config.injector;
  769. // If the loaded config was a module, use that as the module/module injector going
  770. // forward. Otherwise, continue using the current module/module injector.
  771. return this.processRoutes(config.injector ?? injector, config.routes);
  772. }));
  773. if (route.loadComponent && !route._loadedComponent) {
  774. const loadComponent$ = this.loader.loadComponent(route);
  775. return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
  776. }
  777. else {
  778. return recursiveLoadChildren$;
  779. }
  780. });
  781. }
  782. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
  783. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterPreloader, providedIn: 'root' });
  784. }
  785. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterPreloader, decorators: [{
  786. type: Injectable,
  787. args: [{ providedIn: 'root' }]
  788. }], ctorParameters: () => [{ type: Router }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }] });
  789. const ROUTER_SCROLLER = new InjectionToken('');
  790. class RouterScroller {
  791. urlSerializer;
  792. transitions;
  793. viewportScroller;
  794. zone;
  795. options;
  796. routerEventsSubscription;
  797. scrollEventsSubscription;
  798. lastId = 0;
  799. lastSource = 'imperative';
  800. restoredId = 0;
  801. store = {};
  802. /** @docs-private */
  803. constructor(urlSerializer, transitions, viewportScroller, zone, options = {}) {
  804. this.urlSerializer = urlSerializer;
  805. this.transitions = transitions;
  806. this.viewportScroller = viewportScroller;
  807. this.zone = zone;
  808. this.options = options;
  809. // Default both options to 'disabled'
  810. options.scrollPositionRestoration ||= 'disabled';
  811. options.anchorScrolling ||= 'disabled';
  812. }
  813. init() {
  814. // we want to disable the automatic scrolling because having two places
  815. // responsible for scrolling results race conditions, especially given
  816. // that browser don't implement this behavior consistently
  817. if (this.options.scrollPositionRestoration !== 'disabled') {
  818. this.viewportScroller.setHistoryScrollRestoration('manual');
  819. }
  820. this.routerEventsSubscription = this.createScrollEvents();
  821. this.scrollEventsSubscription = this.consumeScrollEvents();
  822. }
  823. createScrollEvents() {
  824. return this.transitions.events.subscribe((e) => {
  825. if (e instanceof NavigationStart) {
  826. // store the scroll position of the current stable navigations.
  827. this.store[this.lastId] = this.viewportScroller.getScrollPosition();
  828. this.lastSource = e.navigationTrigger;
  829. this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;
  830. }
  831. else if (e instanceof NavigationEnd) {
  832. this.lastId = e.id;
  833. this.scheduleScrollEvent(e, this.urlSerializer.parse(e.urlAfterRedirects).fragment);
  834. }
  835. else if (e instanceof NavigationSkipped &&
  836. e.code === NavigationSkippedCode.IgnoredSameUrlNavigation) {
  837. this.lastSource = undefined;
  838. this.restoredId = 0;
  839. this.scheduleScrollEvent(e, this.urlSerializer.parse(e.url).fragment);
  840. }
  841. });
  842. }
  843. consumeScrollEvents() {
  844. return this.transitions.events.subscribe((e) => {
  845. if (!(e instanceof Scroll))
  846. return;
  847. // a popstate event. The pop state event will always ignore anchor scrolling.
  848. if (e.position) {
  849. if (this.options.scrollPositionRestoration === 'top') {
  850. this.viewportScroller.scrollToPosition([0, 0]);
  851. }
  852. else if (this.options.scrollPositionRestoration === 'enabled') {
  853. this.viewportScroller.scrollToPosition(e.position);
  854. }
  855. // imperative navigation "forward"
  856. }
  857. else {
  858. if (e.anchor && this.options.anchorScrolling === 'enabled') {
  859. this.viewportScroller.scrollToAnchor(e.anchor);
  860. }
  861. else if (this.options.scrollPositionRestoration !== 'disabled') {
  862. this.viewportScroller.scrollToPosition([0, 0]);
  863. }
  864. }
  865. });
  866. }
  867. scheduleScrollEvent(routerEvent, anchor) {
  868. this.zone.runOutsideAngular(() => {
  869. // The scroll event needs to be delayed until after change detection. Otherwise, we may
  870. // attempt to restore the scroll position before the router outlet has fully rendered the
  871. // component by executing its update block of the template function.
  872. setTimeout(() => {
  873. this.zone.run(() => {
  874. this.transitions.events.next(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
  875. });
  876. }, 0);
  877. });
  878. }
  879. /** @docs-private */
  880. ngOnDestroy() {
  881. this.routerEventsSubscription?.unsubscribe();
  882. this.scrollEventsSubscription?.unsubscribe();
  883. }
  884. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
  885. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterScroller });
  886. }
  887. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterScroller, decorators: [{
  888. type: Injectable
  889. }], ctorParameters: () => [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }] });
  890. /**
  891. * Sets up providers necessary to enable `Router` functionality for the application.
  892. * Allows to configure a set of routes as well as extra features that should be enabled.
  893. *
  894. * @usageNotes
  895. *
  896. * Basic example of how you can add a Router to your application:
  897. * ```ts
  898. * const appRoutes: Routes = [];
  899. * bootstrapApplication(AppComponent, {
  900. * providers: [provideRouter(appRoutes)]
  901. * });
  902. * ```
  903. *
  904. * You can also enable optional features in the Router by adding functions from the `RouterFeatures`
  905. * type:
  906. * ```ts
  907. * const appRoutes: Routes = [];
  908. * bootstrapApplication(AppComponent,
  909. * {
  910. * providers: [
  911. * provideRouter(appRoutes,
  912. * withDebugTracing(),
  913. * withRouterConfig({paramsInheritanceStrategy: 'always'}))
  914. * ]
  915. * }
  916. * );
  917. * ```
  918. *
  919. * @see {@link RouterFeatures}
  920. *
  921. * @publicApi
  922. * @param routes A set of `Route`s to use for the application routing table.
  923. * @param features Optional features to configure additional router behaviors.
  924. * @returns A set of providers to setup a Router.
  925. */
  926. function provideRouter(routes, ...features) {
  927. return makeEnvironmentProviders([
  928. { provide: ROUTES, multi: true, useValue: routes },
  929. typeof ngDevMode === 'undefined' || ngDevMode
  930. ? { provide: ROUTER_IS_PROVIDED, useValue: true }
  931. : [],
  932. { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
  933. { provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: getBootstrapListener },
  934. features.map((feature) => feature.ɵproviders),
  935. ]);
  936. }
  937. function rootRoute(router) {
  938. return router.routerState.root;
  939. }
  940. /**
  941. * Helper function to create an object that represents a Router feature.
  942. */
  943. function routerFeature(kind, providers) {
  944. return { ɵkind: kind, ɵproviders: providers };
  945. }
  946. /**
  947. * An Injection token used to indicate whether `provideRouter` or `RouterModule.forRoot` was ever
  948. * called.
  949. */
  950. const ROUTER_IS_PROVIDED = new InjectionToken('', {
  951. providedIn: 'root',
  952. factory: () => false,
  953. });
  954. const routerIsProvidedDevModeCheck = {
  955. provide: ENVIRONMENT_INITIALIZER,
  956. multi: true,
  957. useFactory() {
  958. return () => {
  959. if (!inject(ROUTER_IS_PROVIDED)) {
  960. console.warn('`provideRoutes` was called without `provideRouter` or `RouterModule.forRoot`. ' +
  961. 'This is likely a mistake.');
  962. }
  963. };
  964. },
  965. };
  966. /**
  967. * Registers a DI provider for a set of routes.
  968. * @param routes The route configuration to provide.
  969. *
  970. * @usageNotes
  971. *
  972. * ```ts
  973. * @NgModule({
  974. * providers: [provideRoutes(ROUTES)]
  975. * })
  976. * class LazyLoadedChildModule {}
  977. * ```
  978. *
  979. * @deprecated If necessary, provide routes using the `ROUTES` `InjectionToken`.
  980. * @see {@link ROUTES}
  981. * @publicApi
  982. */
  983. function provideRoutes(routes) {
  984. return [
  985. { provide: ROUTES, multi: true, useValue: routes },
  986. typeof ngDevMode === 'undefined' || ngDevMode ? routerIsProvidedDevModeCheck : [],
  987. ];
  988. }
  989. /**
  990. * Enables customizable scrolling behavior for router navigations.
  991. *
  992. * @usageNotes
  993. *
  994. * Basic example of how you can enable scrolling feature:
  995. * ```ts
  996. * const appRoutes: Routes = [];
  997. * bootstrapApplication(AppComponent,
  998. * {
  999. * providers: [
  1000. * provideRouter(appRoutes, withInMemoryScrolling())
  1001. * ]
  1002. * }
  1003. * );
  1004. * ```
  1005. *
  1006. * @see {@link provideRouter}
  1007. * @see {@link ViewportScroller}
  1008. *
  1009. * @publicApi
  1010. * @param options Set of configuration parameters to customize scrolling behavior, see
  1011. * `InMemoryScrollingOptions` for additional information.
  1012. * @returns A set of providers for use with `provideRouter`.
  1013. */
  1014. function withInMemoryScrolling(options = {}) {
  1015. const providers = [
  1016. {
  1017. provide: ROUTER_SCROLLER,
  1018. useFactory: () => {
  1019. const viewportScroller = inject(ViewportScroller);
  1020. const zone = inject(NgZone);
  1021. const transitions = inject(NavigationTransitions);
  1022. const urlSerializer = inject(UrlSerializer);
  1023. return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, options);
  1024. },
  1025. },
  1026. ];
  1027. return routerFeature(4 /* RouterFeatureKind.InMemoryScrollingFeature */, providers);
  1028. }
  1029. function getBootstrapListener() {
  1030. const injector = inject(Injector);
  1031. return (bootstrappedComponentRef) => {
  1032. const ref = injector.get(ApplicationRef);
  1033. if (bootstrappedComponentRef !== ref.components[0]) {
  1034. return;
  1035. }
  1036. const router = injector.get(Router);
  1037. const bootstrapDone = injector.get(BOOTSTRAP_DONE);
  1038. if (injector.get(INITIAL_NAVIGATION) === 1 /* InitialNavigation.EnabledNonBlocking */) {
  1039. router.initialNavigation();
  1040. }
  1041. injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();
  1042. injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();
  1043. router.resetRootComponentType(ref.componentTypes[0]);
  1044. if (!bootstrapDone.closed) {
  1045. bootstrapDone.next();
  1046. bootstrapDone.complete();
  1047. bootstrapDone.unsubscribe();
  1048. }
  1049. };
  1050. }
  1051. /**
  1052. * A subject used to indicate that the bootstrapping phase is done. When initial navigation is
  1053. * `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing
  1054. * to the activation phase.
  1055. */
  1056. const BOOTSTRAP_DONE = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'bootstrap done indicator' : '', {
  1057. factory: () => {
  1058. return new Subject();
  1059. },
  1060. });
  1061. const INITIAL_NAVIGATION = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'initial navigation' : '', { providedIn: 'root', factory: () => 1 /* InitialNavigation.EnabledNonBlocking */ });
  1062. /**
  1063. * Configures initial navigation to start before the root component is created.
  1064. *
  1065. * The bootstrap is blocked until the initial navigation is complete. This should be set in case
  1066. * you use [server-side rendering](guide/ssr), but do not enable [hydration](guide/hydration) for
  1067. * your application.
  1068. *
  1069. * @usageNotes
  1070. *
  1071. * Basic example of how you can enable this navigation behavior:
  1072. * ```ts
  1073. * const appRoutes: Routes = [];
  1074. * bootstrapApplication(AppComponent,
  1075. * {
  1076. * providers: [
  1077. * provideRouter(appRoutes, withEnabledBlockingInitialNavigation())
  1078. * ]
  1079. * }
  1080. * );
  1081. * ```
  1082. *
  1083. * @see {@link provideRouter}
  1084. *
  1085. * @publicApi
  1086. * @returns A set of providers for use with `provideRouter`.
  1087. */
  1088. function withEnabledBlockingInitialNavigation() {
  1089. const providers = [
  1090. { provide: INITIAL_NAVIGATION, useValue: 0 /* InitialNavigation.EnabledBlocking */ },
  1091. provideAppInitializer(() => {
  1092. const injector = inject(Injector);
  1093. const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve());
  1094. return locationInitialized.then(() => {
  1095. return new Promise((resolve) => {
  1096. const router = injector.get(Router);
  1097. const bootstrapDone = injector.get(BOOTSTRAP_DONE);
  1098. afterNextNavigation(router, () => {
  1099. // Unblock APP_INITIALIZER in case the initial navigation was canceled or errored
  1100. // without a redirect.
  1101. resolve(true);
  1102. });
  1103. injector.get(NavigationTransitions).afterPreactivation = () => {
  1104. // Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we
  1105. // assume activation will complete successfully (even though this is not
  1106. // guaranteed).
  1107. resolve(true);
  1108. return bootstrapDone.closed ? of(void 0) : bootstrapDone;
  1109. };
  1110. router.initialNavigation();
  1111. });
  1112. });
  1113. }),
  1114. ];
  1115. return routerFeature(2 /* RouterFeatureKind.EnabledBlockingInitialNavigationFeature */, providers);
  1116. }
  1117. /**
  1118. * Disables initial navigation.
  1119. *
  1120. * Use if there is a reason to have more control over when the router starts its initial navigation
  1121. * due to some complex initialization logic.
  1122. *
  1123. * @usageNotes
  1124. *
  1125. * Basic example of how you can disable initial navigation:
  1126. * ```ts
  1127. * const appRoutes: Routes = [];
  1128. * bootstrapApplication(AppComponent,
  1129. * {
  1130. * providers: [
  1131. * provideRouter(appRoutes, withDisabledInitialNavigation())
  1132. * ]
  1133. * }
  1134. * );
  1135. * ```
  1136. *
  1137. * @see {@link provideRouter}
  1138. *
  1139. * @returns A set of providers for use with `provideRouter`.
  1140. *
  1141. * @publicApi
  1142. */
  1143. function withDisabledInitialNavigation() {
  1144. const providers = [
  1145. provideAppInitializer(() => {
  1146. inject(Router).setUpLocationChangeListener();
  1147. }),
  1148. { provide: INITIAL_NAVIGATION, useValue: 2 /* InitialNavigation.Disabled */ },
  1149. ];
  1150. return routerFeature(3 /* RouterFeatureKind.DisabledInitialNavigationFeature */, providers);
  1151. }
  1152. /**
  1153. * Enables logging of all internal navigation events to the console.
  1154. * Extra logging might be useful for debugging purposes to inspect Router event sequence.
  1155. *
  1156. * @usageNotes
  1157. *
  1158. * Basic example of how you can enable debug tracing:
  1159. * ```ts
  1160. * const appRoutes: Routes = [];
  1161. * bootstrapApplication(AppComponent,
  1162. * {
  1163. * providers: [
  1164. * provideRouter(appRoutes, withDebugTracing())
  1165. * ]
  1166. * }
  1167. * );
  1168. * ```
  1169. *
  1170. * @see {@link provideRouter}
  1171. *
  1172. * @returns A set of providers for use with `provideRouter`.
  1173. *
  1174. * @publicApi
  1175. */
  1176. function withDebugTracing() {
  1177. let providers = [];
  1178. if (typeof ngDevMode === 'undefined' || ngDevMode) {
  1179. providers = [
  1180. {
  1181. provide: ENVIRONMENT_INITIALIZER,
  1182. multi: true,
  1183. useFactory: () => {
  1184. const router = inject(Router);
  1185. return () => router.events.subscribe((e) => {
  1186. // tslint:disable:no-console
  1187. console.group?.(`Router Event: ${e.constructor.name}`);
  1188. console.log(stringifyEvent(e));
  1189. console.log(e);
  1190. console.groupEnd?.();
  1191. // tslint:enable:no-console
  1192. });
  1193. },
  1194. },
  1195. ];
  1196. }
  1197. else {
  1198. providers = [];
  1199. }
  1200. return routerFeature(1 /* RouterFeatureKind.DebugTracingFeature */, providers);
  1201. }
  1202. const ROUTER_PRELOADER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'router preloader' : '');
  1203. /**
  1204. * Allows to configure a preloading strategy to use. The strategy is configured by providing a
  1205. * reference to a class that implements a `PreloadingStrategy`.
  1206. *
  1207. * @usageNotes
  1208. *
  1209. * Basic example of how you can configure preloading:
  1210. * ```ts
  1211. * const appRoutes: Routes = [];
  1212. * bootstrapApplication(AppComponent,
  1213. * {
  1214. * providers: [
  1215. * provideRouter(appRoutes, withPreloading(PreloadAllModules))
  1216. * ]
  1217. * }
  1218. * );
  1219. * ```
  1220. *
  1221. * @see {@link provideRouter}
  1222. *
  1223. * @param preloadingStrategy A reference to a class that implements a `PreloadingStrategy` that
  1224. * should be used.
  1225. * @returns A set of providers for use with `provideRouter`.
  1226. *
  1227. * @publicApi
  1228. */
  1229. function withPreloading(preloadingStrategy) {
  1230. const providers = [
  1231. { provide: ROUTER_PRELOADER, useExisting: RouterPreloader },
  1232. { provide: PreloadingStrategy, useExisting: preloadingStrategy },
  1233. ];
  1234. return routerFeature(0 /* RouterFeatureKind.PreloadingFeature */, providers);
  1235. }
  1236. /**
  1237. * Allows to provide extra parameters to configure Router.
  1238. *
  1239. * @usageNotes
  1240. *
  1241. * Basic example of how you can provide extra configuration options:
  1242. * ```ts
  1243. * const appRoutes: Routes = [];
  1244. * bootstrapApplication(AppComponent,
  1245. * {
  1246. * providers: [
  1247. * provideRouter(appRoutes, withRouterConfig({
  1248. * onSameUrlNavigation: 'reload'
  1249. * }))
  1250. * ]
  1251. * }
  1252. * );
  1253. * ```
  1254. *
  1255. * @see {@link provideRouter}
  1256. *
  1257. * @param options A set of parameters to configure Router, see `RouterConfigOptions` for
  1258. * additional information.
  1259. * @returns A set of providers for use with `provideRouter`.
  1260. *
  1261. * @publicApi
  1262. */
  1263. function withRouterConfig(options) {
  1264. const providers = [{ provide: ROUTER_CONFIGURATION, useValue: options }];
  1265. return routerFeature(5 /* RouterFeatureKind.RouterConfigurationFeature */, providers);
  1266. }
  1267. /**
  1268. * Provides the location strategy that uses the URL fragment instead of the history API.
  1269. *
  1270. * @usageNotes
  1271. *
  1272. * Basic example of how you can use the hash location option:
  1273. * ```ts
  1274. * const appRoutes: Routes = [];
  1275. * bootstrapApplication(AppComponent,
  1276. * {
  1277. * providers: [
  1278. * provideRouter(appRoutes, withHashLocation())
  1279. * ]
  1280. * }
  1281. * );
  1282. * ```
  1283. *
  1284. * @see {@link provideRouter}
  1285. * @see {@link /api/common/HashLocationStrategy HashLocationStrategy}
  1286. *
  1287. * @returns A set of providers for use with `provideRouter`.
  1288. *
  1289. * @publicApi
  1290. */
  1291. function withHashLocation() {
  1292. const providers = [{ provide: LocationStrategy, useClass: HashLocationStrategy }];
  1293. return routerFeature(6 /* RouterFeatureKind.RouterHashLocationFeature */, providers);
  1294. }
  1295. /**
  1296. * Provides a function which is called when a navigation error occurs.
  1297. *
  1298. * This function is run inside application's [injection context](guide/di/dependency-injection-context)
  1299. * so you can use the [`inject`](api/core/inject) function.
  1300. *
  1301. * This function can return a `RedirectCommand` to convert the error to a redirect, similar to returning
  1302. * a `UrlTree` or `RedirectCommand` from a guard. This will also prevent the `Router` from emitting
  1303. * `NavigationError`; it will instead emit `NavigationCancel` with code NavigationCancellationCode.Redirect.
  1304. * Return values other than `RedirectCommand` are ignored and do not change any behavior with respect to
  1305. * how the `Router` handles the error.
  1306. *
  1307. * @usageNotes
  1308. *
  1309. * Basic example of how you can use the error handler option:
  1310. * ```ts
  1311. * const appRoutes: Routes = [];
  1312. * bootstrapApplication(AppComponent,
  1313. * {
  1314. * providers: [
  1315. * provideRouter(appRoutes, withNavigationErrorHandler((e: NavigationError) =>
  1316. * inject(MyErrorTracker).trackError(e)))
  1317. * ]
  1318. * }
  1319. * );
  1320. * ```
  1321. *
  1322. * @see {@link NavigationError}
  1323. * @see {@link /api/core/inject inject}
  1324. * @see {@link runInInjectionContext}
  1325. *
  1326. * @returns A set of providers for use with `provideRouter`.
  1327. *
  1328. * @publicApi
  1329. */
  1330. function withNavigationErrorHandler(handler) {
  1331. const providers = [
  1332. {
  1333. provide: NAVIGATION_ERROR_HANDLER,
  1334. useValue: handler,
  1335. },
  1336. ];
  1337. return routerFeature(7 /* RouterFeatureKind.NavigationErrorHandlerFeature */, providers);
  1338. }
  1339. /**
  1340. * Enables binding information from the `Router` state directly to the inputs of the component in
  1341. * `Route` configurations.
  1342. *
  1343. * @usageNotes
  1344. *
  1345. * Basic example of how you can enable the feature:
  1346. * ```ts
  1347. * const appRoutes: Routes = [];
  1348. * bootstrapApplication(AppComponent,
  1349. * {
  1350. * providers: [
  1351. * provideRouter(appRoutes, withComponentInputBinding())
  1352. * ]
  1353. * }
  1354. * );
  1355. * ```
  1356. *
  1357. * The router bindings information from any of the following sources:
  1358. *
  1359. * - query parameters
  1360. * - path and matrix parameters
  1361. * - static route data
  1362. * - data from resolvers
  1363. *
  1364. * Duplicate keys are resolved in the same order from above, from least to greatest,
  1365. * meaning that resolvers have the highest precedence and override any of the other information
  1366. * from the route.
  1367. *
  1368. * Importantly, when an input does not have an item in the route data with a matching key, this
  1369. * input is set to `undefined`. This prevents previous information from being
  1370. * retained if the data got removed from the route (i.e. if a query parameter is removed).
  1371. * Default values can be provided with a resolver on the route to ensure the value is always present
  1372. * or an input and use an input transform in the component.
  1373. *
  1374. * @see {@link /guide/components/inputs#input-transforms Input Transforms}
  1375. * @returns A set of providers for use with `provideRouter`.
  1376. */
  1377. function withComponentInputBinding() {
  1378. const providers = [
  1379. RoutedComponentInputBinder,
  1380. { provide: INPUT_BINDER, useExisting: RoutedComponentInputBinder },
  1381. ];
  1382. return routerFeature(8 /* RouterFeatureKind.ComponentInputBindingFeature */, providers);
  1383. }
  1384. /**
  1385. * Enables view transitions in the Router by running the route activation and deactivation inside of
  1386. * `document.startViewTransition`.
  1387. *
  1388. * Note: The View Transitions API is not available in all browsers. If the browser does not support
  1389. * view transitions, the Router will not attempt to start a view transition and continue processing
  1390. * the navigation as usual.
  1391. *
  1392. * @usageNotes
  1393. *
  1394. * Basic example of how you can enable the feature:
  1395. * ```ts
  1396. * const appRoutes: Routes = [];
  1397. * bootstrapApplication(AppComponent,
  1398. * {
  1399. * providers: [
  1400. * provideRouter(appRoutes, withViewTransitions())
  1401. * ]
  1402. * }
  1403. * );
  1404. * ```
  1405. *
  1406. * @returns A set of providers for use with `provideRouter`.
  1407. * @see https://developer.chrome.com/docs/web-platform/view-transitions/
  1408. * @see https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
  1409. * @developerPreview
  1410. */
  1411. function withViewTransitions(options) {
  1412. _performanceMarkFeature('NgRouterViewTransitions');
  1413. const providers = [
  1414. { provide: CREATE_VIEW_TRANSITION, useValue: createViewTransition },
  1415. {
  1416. provide: VIEW_TRANSITION_OPTIONS,
  1417. useValue: { skipNextTransition: !!options?.skipInitialTransition, ...options },
  1418. },
  1419. ];
  1420. return routerFeature(9 /* RouterFeatureKind.ViewTransitionsFeature */, providers);
  1421. }
  1422. /**
  1423. * The directives defined in the `RouterModule`.
  1424. */
  1425. const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent];
  1426. /**
  1427. * @docsNotRequired
  1428. */
  1429. const ROUTER_FORROOT_GUARD = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'router duplicate forRoot guard' : '');
  1430. // TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept
  1431. // here to avoid a breaking change whereby the provider order matters based on where the
  1432. // `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a "breaking"
  1433. // change in a major version.
  1434. const ROUTER_PROVIDERS = [
  1435. Location,
  1436. { provide: UrlSerializer, useClass: DefaultUrlSerializer },
  1437. Router,
  1438. ChildrenOutletContexts,
  1439. { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
  1440. RouterConfigLoader,
  1441. // Only used to warn when `provideRoutes` is used without `RouterModule` or `provideRouter`. Can
  1442. // be removed when `provideRoutes` is removed.
  1443. typeof ngDevMode === 'undefined' || ngDevMode
  1444. ? { provide: ROUTER_IS_PROVIDED, useValue: true }
  1445. : [],
  1446. ];
  1447. /**
  1448. * @description
  1449. *
  1450. * Adds directives and providers for in-app navigation among views defined in an application.
  1451. * Use the Angular `Router` service to declaratively specify application states and manage state
  1452. * transitions.
  1453. *
  1454. * You can import this NgModule multiple times, once for each lazy-loaded bundle.
  1455. * However, only one `Router` service can be active.
  1456. * To ensure this, there are two ways to register routes when importing this module:
  1457. *
  1458. * * The `forRoot()` method creates an `NgModule` that contains all the directives, the given
  1459. * routes, and the `Router` service itself.
  1460. * * The `forChild()` method creates an `NgModule` that contains all the directives and the given
  1461. * routes, but does not include the `Router` service.
  1462. *
  1463. * @see [Routing and Navigation guide](guide/routing/common-router-tasks) for an
  1464. * overview of how the `Router` service should be used.
  1465. *
  1466. * @publicApi
  1467. */
  1468. class RouterModule {
  1469. constructor() {
  1470. if (typeof ngDevMode === 'undefined' || ngDevMode) {
  1471. inject(ROUTER_FORROOT_GUARD, { optional: true });
  1472. }
  1473. }
  1474. /**
  1475. * Creates and configures a module with all the router providers and directives.
  1476. * Optionally sets up an application listener to perform an initial navigation.
  1477. *
  1478. * When registering the NgModule at the root, import as follows:
  1479. *
  1480. * ```ts
  1481. * @NgModule({
  1482. * imports: [RouterModule.forRoot(ROUTES)]
  1483. * })
  1484. * class MyNgModule {}
  1485. * ```
  1486. *
  1487. * @param routes An array of `Route` objects that define the navigation paths for the application.
  1488. * @param config An `ExtraOptions` configuration object that controls how navigation is performed.
  1489. * @return The new `NgModule`.
  1490. *
  1491. */
  1492. static forRoot(routes, config) {
  1493. return {
  1494. ngModule: RouterModule,
  1495. providers: [
  1496. ROUTER_PROVIDERS,
  1497. typeof ngDevMode === 'undefined' || ngDevMode
  1498. ? config?.enableTracing
  1499. ? withDebugTracing().ɵproviders
  1500. : []
  1501. : [],
  1502. { provide: ROUTES, multi: true, useValue: routes },
  1503. typeof ngDevMode === 'undefined' || ngDevMode
  1504. ? {
  1505. provide: ROUTER_FORROOT_GUARD,
  1506. useFactory: provideForRootGuard,
  1507. deps: [[Router, new Optional(), new SkipSelf()]],
  1508. }
  1509. : [],
  1510. config?.errorHandler
  1511. ? {
  1512. provide: NAVIGATION_ERROR_HANDLER,
  1513. useValue: config.errorHandler,
  1514. }
  1515. : [],
  1516. { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} },
  1517. config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(),
  1518. provideRouterScroller(),
  1519. config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [],
  1520. config?.initialNavigation ? provideInitialNavigation(config) : [],
  1521. config?.bindToComponentInputs ? withComponentInputBinding().ɵproviders : [],
  1522. config?.enableViewTransitions ? withViewTransitions().ɵproviders : [],
  1523. provideRouterInitializer(),
  1524. ],
  1525. };
  1526. }
  1527. /**
  1528. * Creates a module with all the router directives and a provider registering routes,
  1529. * without creating a new Router service.
  1530. * When registering for submodules and lazy-loaded submodules, create the NgModule as follows:
  1531. *
  1532. * ```ts
  1533. * @NgModule({
  1534. * imports: [RouterModule.forChild(ROUTES)]
  1535. * })
  1536. * class MyNgModule {}
  1537. * ```
  1538. *
  1539. * @param routes An array of `Route` objects that define the navigation paths for the submodule.
  1540. * @return The new NgModule.
  1541. *
  1542. */
  1543. static forChild(routes) {
  1544. return {
  1545. ngModule: RouterModule,
  1546. providers: [{ provide: ROUTES, multi: true, useValue: routes }],
  1547. };
  1548. }
  1549. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
  1550. static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.13", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent] });
  1551. static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterModule });
  1552. }
  1553. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: RouterModule, decorators: [{
  1554. type: NgModule,
  1555. args: [{
  1556. imports: ROUTER_DIRECTIVES,
  1557. exports: ROUTER_DIRECTIVES,
  1558. }]
  1559. }], ctorParameters: () => [] });
  1560. /**
  1561. * For internal use by `RouterModule` only. Note that this differs from `withInMemoryRouterScroller`
  1562. * because it reads from the `ExtraOptions` which should not be used in the standalone world.
  1563. */
  1564. function provideRouterScroller() {
  1565. return {
  1566. provide: ROUTER_SCROLLER,
  1567. useFactory: () => {
  1568. const viewportScroller = inject(ViewportScroller);
  1569. const zone = inject(NgZone);
  1570. const config = inject(ROUTER_CONFIGURATION);
  1571. const transitions = inject(NavigationTransitions);
  1572. const urlSerializer = inject(UrlSerializer);
  1573. if (config.scrollOffset) {
  1574. viewportScroller.setOffset(config.scrollOffset);
  1575. }
  1576. return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, config);
  1577. },
  1578. };
  1579. }
  1580. // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` should
  1581. // provide hash location directly via `{provide: LocationStrategy, useClass: HashLocationStrategy}`.
  1582. function provideHashLocationStrategy() {
  1583. return { provide: LocationStrategy, useClass: HashLocationStrategy };
  1584. }
  1585. // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` does not
  1586. // need this at all because `PathLocationStrategy` is the default factory for `LocationStrategy`.
  1587. function providePathLocationStrategy() {
  1588. return { provide: LocationStrategy, useClass: PathLocationStrategy };
  1589. }
  1590. function provideForRootGuard(router) {
  1591. if (router) {
  1592. throw new _RuntimeError(4007 /* RuntimeErrorCode.FOR_ROOT_CALLED_TWICE */, `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` +
  1593. ` Lazy loaded modules should use RouterModule.forChild() instead.`);
  1594. }
  1595. return 'guarded';
  1596. }
  1597. // Note: For internal use only with `RouterModule`. Standalone router setup with `provideRouter`
  1598. // users call `withXInitialNavigation` directly.
  1599. function provideInitialNavigation(config) {
  1600. return [
  1601. config.initialNavigation === 'disabled' ? withDisabledInitialNavigation().ɵproviders : [],
  1602. config.initialNavigation === 'enabledBlocking'
  1603. ? withEnabledBlockingInitialNavigation().ɵproviders
  1604. : [],
  1605. ];
  1606. }
  1607. // TODO(atscott): This should not be in the public API
  1608. /**
  1609. * A DI token for the router initializer that
  1610. * is called after the app is bootstrapped.
  1611. *
  1612. * @publicApi
  1613. */
  1614. const ROUTER_INITIALIZER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'Router Initializer' : '');
  1615. function provideRouterInitializer() {
  1616. return [
  1617. // ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just
  1618. // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER.
  1619. { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener },
  1620. { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
  1621. ];
  1622. }
  1623. export { NoPreloading, PreloadAllModules, PreloadingStrategy, ROUTER_INITIALIZER, ROUTER_PROVIDERS, RouterLink, RouterLinkActive, RouterModule, RouterPreloader, provideRouter, provideRoutes, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, withViewTransitions };
  1624. //# sourceMappingURL=router_module-DTJgGWLd.mjs.map