From b00121c9a6e4b9601008d303a9ea74815d3d6ac5 Mon Sep 17 00:00:00 2001 From: Judy Bogart Date: Wed, 15 Jul 2020 09:43:00 -0700 Subject: [PATCH] docs: update reference doc for router guards and resolvers (#38079) Complete and clarify descriptions and example of the guard and resolver functions in Router API documentation. PR Close #38079 --- packages/router/src/interfaces.ts | 109 +++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 23 deletions(-) diff --git a/packages/router/src/interfaces.ts b/packages/router/src/interfaces.ts index fa645d50bf..c072fa690f 100644 --- a/packages/router/src/interfaces.ts +++ b/packages/router/src/interfaces.ts @@ -17,10 +17,12 @@ import {UrlSegment, UrlTree} from './url_tree'; * @description * * Interface that a class can implement to be a guard deciding if a route can be activated. - * If all guards return `true`, navigation will continue. If any guard returns `false`, - * navigation will be cancelled. If any guard returns a `UrlTree`, current navigation will - * be cancelled and a new navigation will be kicked off to the `UrlTree` returned from the - * guard. + * If all guards return `true`, navigation continues. If any guard returns `false`, + * navigation is cancelled. If any guard returns a `UrlTree`, the current navigation + * is cancelled and a new navigation begins to the `UrlTree` returned from the guard. + * + * The following example implements a `CanActivate` function that checks whether the + * current user has permission to activate the requested route. * * ``` * class UserToken {} @@ -41,7 +43,12 @@ import {UrlSegment, UrlTree} from './url_tree'; * return this.permissions.canActivate(this.currentUser, route.params.id); * } * } + * ``` * + * Here, the defined guard function is provided as part of the `Route` object + * in the router configuration: + * + * ``` * @NgModule({ * imports: [ * RouterModule.forRoot([ @@ -57,7 +64,7 @@ import {UrlSegment, UrlTree} from './url_tree'; * class AppModule {} * ``` * - * You can alternatively provide a function with the `canActivate` signature: + * You can alternatively provide an in-line function with the `canActivate` signature: * * ``` * @NgModule({ @@ -94,10 +101,12 @@ export type CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSn * @description * * Interface that a class can implement to be a guard deciding if a child route can be activated. - * If all guards return `true`, navigation will continue. If any guard returns `false`, - * navigation will be cancelled. If any guard returns a `UrlTree`, current navigation will - * be cancelled and a new navigation will be kicked off to the `UrlTree` returned from the - * guard. + * If all guards return `true`, navigation continues. If any guard returns `false`, + * navigation is cancelled. If any guard returns a `UrlTree`, current navigation + * is cancelled and a new navigation begins to the `UrlTree` returned from the guard. + * + * The following example implements a `CanActivateChild` function that checks whether the + * current user has permission to activate the requested child route. * * ``` * class UserToken {} @@ -118,7 +127,12 @@ export type CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSn * return this.permissions.canActivate(this.currentUser, route.params.id); * } * } + * ``` * + * Here, the defined guard function is provided as part of the `Route` object + * in the router configuration: + * + * ``` * @NgModule({ * imports: [ * RouterModule.forRoot([ @@ -139,7 +153,7 @@ export type CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSn * class AppModule {} * ``` * - * You can alternatively provide a function with the `canActivateChild` signature: + * You can alternatively provide an in-line function with the `canActivateChild` signature: * * ``` * @NgModule({ @@ -181,10 +195,12 @@ export type CanActivateChildFn = (childRoute: ActivatedRouteSnapshot, state: Rou * @description * * Interface that a class can implement to be a guard deciding if a route can be deactivated. - * If all guards return `true`, navigation will continue. If any guard returns `false`, - * navigation will be cancelled. If any guard returns a `UrlTree`, current navigation will - * be cancelled and a new navigation will be kicked off to the `UrlTree` returned from the - * guard. + * If all guards return `true`, navigation continues. If any guard returns `false`, + * navigation is cancelled. If any guard returns a `UrlTree`, current navigation + * is cancelled and a new navigation begins to the `UrlTree` returned from the guard. + * + * The following example implements a `CanDeactivate` function that checks whether the + * current user has permission to deactivate the requested route. * * ``` * class UserToken {} @@ -193,6 +209,12 @@ export type CanActivateChildFn = (childRoute: ActivatedRouteSnapshot, state: Rou * return true; * } * } + * ``` + * + * Here, the defined guard function is provided as part of the `Route` object + * in the router configuration: + * + * ``` * * @Injectable() * class CanDeactivateTeam implements CanDeactivate { @@ -223,7 +245,7 @@ export type CanActivateChildFn = (childRoute: ActivatedRouteSnapshot, state: Rou * class AppModule {} * ``` * - * You can alternatively provide a function with the `canDeactivate` signature: + * You can alternatively provide an in-line function with the `canDeactivate` signature: * * ``` * @NgModule({ @@ -266,8 +288,11 @@ export type CanDeactivateFn = * * Interface that classes can implement to be a data provider. * A data provider class can be used with the router to resolve data during navigation. - * The interface defines a `resolve()` method that will be invoked when the navigation starts. - * The router will then wait for the data to be resolved before the route is finally activated. + * The interface defines a `resolve()` method that is invoked when the navigation starts. + * The router waits for the data to be resolved before the route is finally activated. + * + * The following example implements a `resolve()` method that retrieves the data + * needed to activate the requested route. * * ``` * @Injectable({ providedIn: 'root' }) @@ -281,7 +306,13 @@ export type CanDeactivateFn = * return this.service.getHero(route.paramMap.get('id')); * } * } + * ``` * + * Here, the defined `resolve()` function is provided as part of the `Route` object + * in the router configuration: + * + * ``` + * @NgModule({ * imports: [ * RouterModule.forRoot([ @@ -299,7 +330,7 @@ export type CanDeactivateFn = * export class AppRoutingModule {} * ``` * - * You can alternatively provide a function with the `resolve` signature: + * You can alternatively provide an in-line function with the `resolve()` signature: * * ``` * export const myHero: Hero = { @@ -328,6 +359,29 @@ export type CanDeactivateFn = * export class AppModule {} * ``` * + * @usageNotes + * + * When both guard and resolvers are specified, the resolvers are not executed until + * all guards have run and succeeded. + * For example, consider the following route configuration: + * + * ``` + * { + * path: 'base' + * canActivate: [BaseGuard], + * resolve: {data: BaseDataResolver} + * children: [ + * { + * path: 'child', + * guards: [ChildGuard], + * component: ChildComponent, + * resolve: {childData: ChildDataResolver} + * } + * ] + * } + * ``` + * The order of execution is: BaseGuard, ChildGuard, BaseDataResolver, ChildDataResolver. + * * @publicApi */ export interface Resolve { @@ -339,10 +393,13 @@ export interface Resolve { * @description * * Interface that a class can implement to be a guard deciding if children can be loaded. - * If all guards return `true`, navigation will continue. If any guard returns `false`, - * navigation will be cancelled. If any guard returns a `UrlTree`, current navigation will - * be cancelled and a new navigation will be kicked off to the `UrlTree` returned from the - * guard. + * If all guards return `true`, navigation continues. If any guard returns `false`, + * navigation is cancelled. If any guard returns a `UrlTree`, current navigation + * is cancelled and a new navigation starts to the `UrlTree` returned from the guard. + * + * The following example implements a `CanLoad` function that decides whether the + * current user has permission to load requested child routes. + * * * ``` * class UserToken {} @@ -360,6 +417,12 @@ export interface Resolve { * return this.permissions.canLoadChildren(this.currentUser, route, segments); * } * } + * ``` + * + * Here, the defined guard function is provided as part of the `Route` object + * in the router configuration: + * + * ``` * * @NgModule({ * imports: [ @@ -377,7 +440,7 @@ export interface Resolve { * class AppModule {} * ``` * - * You can alternatively provide a function with the `canLoad` signature: + * You can alternatively provide an in-line function with the `canLoad` signature: * * ``` * @NgModule({