/** * @license * Copyright Google Inc. 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.io/license */ import {Route} from './config'; import {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state'; /** * @description * * Identifies the trigger of the navigation. * * * 'imperative'--triggered by `router.navigateByUrl` or `router.navigate`. * * 'popstate'--triggered by a popstate event * * 'hashchange'--triggered by a hashchange event * * @experimental */ export type NavigationTrigger = 'imperative' | 'popstate' | 'hashchange'; /** * @description * * Base for events the Router goes through, as opposed to events tied to a specific * Route. `RouterEvent`s will only be fired one time for any given navigation. * * Example: * * ``` * class MyService { * constructor(public router: Router, logger: Logger) { * router.events.filter(e => e instanceof RouterEvent).subscribe(e => { * logger.log(e.id, e.url); * }); * } * } * ``` * * @experimental */ export class RouterEvent { constructor( /** @docsNotRequired */ public id: number, /** @docsNotRequired */ public url: string) {} } /** * @description * * Represents an event triggered when a navigation starts. * * @stable */ export class NavigationStart extends RouterEvent { /** * Identifies the trigger of the navigation. * * * 'imperative'--triggered by `router.navigateByUrl` or `router.navigate`. * * 'popstate'--triggered by a popstate event * * 'hashchange'--triggered by a hashchange event */ navigationTrigger?: 'imperative'|'popstate'|'hashchange'; /** * This contains the navigation id that pushed the history record that the router navigates * back to. This is not null only when the navigation is triggered by a popstate event. * * The router assigns a navigationId to every router transition/navigation. Even when the user * clicks on the back button in the browser, a new navigation id will be created. So from * the perspective of the router, the router never "goes back". By using the `restoredState` * and its navigationId, you can implement behavior that differentiates between creating new * states * and popstate events. In the latter case you can restore some remembered state (e.g., scroll * position). */ restoredState?: {navigationId: number}|null; constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ navigationTrigger: 'imperative'|'popstate'|'hashchange' = 'imperative', /** @docsNotRequired */ restoredState: {navigationId: number}|null = null) { super(id, url); this.navigationTrigger = navigationTrigger; this.restoredState = restoredState; } /** @docsNotRequired */ toString(): string { return `NavigationStart(id: ${this.id}, url: '${this.url}')`; } } /** * @description * * Represents an event triggered when a navigation ends successfully. * * @stable */ export class NavigationEnd extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public urlAfterRedirects: string) { super(id, url); } /** @docsNotRequired */ toString(): string { return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`; } } /** * @description * * Represents an event triggered when a navigation is canceled. * * @stable */ export class NavigationCancel extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public reason: string) { super(id, url); } /** @docsNotRequired */ toString(): string { return `NavigationCancel(id: ${this.id}, url: '${this.url}')`; } } /** * @description * * Represents an event triggered when a navigation fails due to an unexpected error. * * @stable */ export class NavigationError extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public error: any) { super(id, url); } /** @docsNotRequired */ toString(): string { return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`; } } /** * @description * * Represents an event triggered when routes are recognized. * * @stable */ export class RoutesRecognized extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public urlAfterRedirects: string, /** @docsNotRequired */ public state: RouterStateSnapshot) { super(id, url); } /** @docsNotRequired */ toString(): string { return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * @description * * Represents the start of the Guard phase of routing. * * @experimental */ export class GuardsCheckStart extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public urlAfterRedirects: string, /** @docsNotRequired */ public state: RouterStateSnapshot) { super(id, url); } toString(): string { return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * @description * * Represents the end of the Guard phase of routing. * * @experimental */ export class GuardsCheckEnd extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public urlAfterRedirects: string, /** @docsNotRequired */ public state: RouterStateSnapshot, /** @docsNotRequired */ public shouldActivate: boolean) { super(id, url); } toString(): string { return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`; } } /** * @description * * Represents the start of the Resolve phase of routing. The timing of this * event may change, thus it's experimental. In the current iteration it will run * in the "resolve" phase whether there's things to resolve or not. In the future this * behavior may change to only run when there are things to be resolved. * * @experimental */ export class ResolveStart extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public urlAfterRedirects: string, /** @docsNotRequired */ public state: RouterStateSnapshot) { super(id, url); } toString(): string { return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * @description * * Represents the end of the Resolve phase of routing. See note on * `ResolveStart` for use of this experimental API. * * @experimental */ export class ResolveEnd extends RouterEvent { constructor( /** @docsNotRequired */ id: number, /** @docsNotRequired */ url: string, /** @docsNotRequired */ public urlAfterRedirects: string, /** @docsNotRequired */ public state: RouterStateSnapshot) { super(id, url); } toString(): string { return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * @description * * Represents an event triggered before lazy loading a route config. * * @experimental */ export class RouteConfigLoadStart { constructor( /** @docsNotRequired */ public route: Route) {} toString(): string { return `RouteConfigLoadStart(path: ${this.route.path})`; } } /** * @description * * Represents an event triggered when a route has been lazy loaded. * * @experimental */ export class RouteConfigLoadEnd { constructor( /** @docsNotRequired */ public route: Route) {} toString(): string { return `RouteConfigLoadEnd(path: ${this.route.path})`; } } /** * @description * * Represents the start of end of the Resolve phase of routing. See note on * `ChildActivationEnd` for use of this experimental API. * * @experimental */ export class ChildActivationStart { constructor( /** @docsNotRequired */ public snapshot: ActivatedRouteSnapshot) {} toString(): string { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ChildActivationStart(path: '${path}')`; } } /** * @description * * Represents the start of end of the Resolve phase of routing. See note on * `ChildActivationStart` for use of this experimental API. * * @experimental */ export class ChildActivationEnd { constructor( /** @docsNotRequired */ public snapshot: ActivatedRouteSnapshot) {} toString(): string { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ChildActivationEnd(path: '${path}')`; } } /** * @description * * Represents the start of end of the Resolve phase of routing. See note on * `ActivationEnd` for use of this experimental API. * * @experimental */ export class ActivationStart { constructor( /** @docsNotRequired */ public snapshot: ActivatedRouteSnapshot) {} toString(): string { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ActivationStart(path: '${path}')`; } } /** * @description * * Represents the start of end of the Resolve phase of routing. See note on * `ActivationStart` for use of this experimental API. * * @experimental */ export class ActivationEnd { constructor( /** @docsNotRequired */ public snapshot: ActivatedRouteSnapshot) {} toString(): string { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ActivationEnd(path: '${path}')`; } } /** * @description * * Represents a router event, allowing you to track the lifecycle of the router. * * The sequence of router events is: * * - `NavigationStart`, * - `RouteConfigLoadStart`, * - `RouteConfigLoadEnd`, * - `RoutesRecognized`, * - `GuardsCheckStart`, * - `ChildActivationStart`, * - `ActivationStart`, * - `GuardsCheckEnd`, * - `ResolveStart`, * - `ResolveEnd`, * - `ActivationEnd` * - `ChildActivationEnd` * - `NavigationEnd`, * - `NavigationCancel`, * - `NavigationError` * * @stable */ export type Event = RouterEvent | RouteConfigLoadStart | RouteConfigLoadEnd | ChildActivationStart | ChildActivationEnd | ActivationStart | ActivationEnd;