From cc0e3d229638b1b54fcfa4ba23926988344217ab Mon Sep 17 00:00:00 2001 From: Brandon Date: Fri, 19 Aug 2016 17:48:09 -0500 Subject: [PATCH] docs(router): Added additional router documentation including cheatsheet updates (#10802) --- modules/@angular/docs/cheatsheet/routing.md | 87 ++++-- modules/@angular/router/src/config.ts | 1 + modules/@angular/router/src/interfaces.ts | 293 ++++++++++++------- modules/@angular/router/src/router.ts | 83 ++++++ modules/@angular/router/src/router_module.ts | 4 +- 5 files changed, 342 insertions(+), 126 deletions(-) diff --git a/modules/@angular/docs/cheatsheet/routing.md b/modules/@angular/docs/cheatsheet/routing.md index a1c3508938..b3d3d5f4ae 100644 --- a/modules/@angular/docs/cheatsheet/routing.md +++ b/modules/@angular/docs/cheatsheet/routing.md @@ -10,7 +10,7 @@ Routing and navigation @cheatsheetItem syntax(ts): `const routes: Routes = [ - { path: '', HomeComponent }, + { path: '', component: HomeComponent }, { path: 'path/:routeParam', component: MyComponent }, { path: 'staticPath', component: ... }, { path: '**', component: ... }, @@ -21,7 +21,7 @@ syntax(ts): const routing = RouterModule.forRoot(routes);`|`Routes` syntax(js): `var routes = [ - { path: '', HomeComponent }, + { path: '', component: HomeComponent }, { path: ':routeParam', component: MyComponent }, { path: 'staticPath', component: ... }, { path: '**', component: ... }, @@ -32,15 +32,23 @@ syntax(js): var routing = ng.router.RouterModule.forRoot(routes);`|`ng.router.Routes` syntax(dart): `@RouteConfig(const [ - const Route(path: 'path', component: MyComponent, name: 'MyCmp' ), -])`|`@RouteConfig` + const Route(path: '', component: HomeComponent, name: 'Home'), + const Route(path: ':routeParam', component: MyComponent, name: 'MyCmp'), + const Route(path: 'staticPath', component: ..., name: 'StaticCmp'), + const Route(path: '**', component: ..., name: 'WildcardCmp'), + const Route(path: '/oldPath', redirectTo: ['/StaticCmp']), + const Route(path: ..., component: ..., data: { message: 'Custom' }) +])class MyComponent() {}`|`@RouteConfig` description: -Configures routes for the application. Supports static, parameterized, redirect and wildcard routes. Also supports custom route data and resolve. +Configures routes for the application. Supports static, parameterized, redirect and wildcard routes. Also supports custom route data{@target ts js} and resolve{@endtarget}. @cheatsheetItem syntax: -``|`router-outlet` +` + + +`|`router-outlet` description: Marks the location to load the component of the active route. @@ -55,7 +63,10 @@ syntax(ts js): `|`[routerLink]` syntax(dart): -`Link`|`[routerLink]` +` + + +`|`[routerLink]` description: Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters and a fragment. Add the '/' prefix to navigate to a root route; add the './' prefix for a child route; add the '../sibling' prefix for a sibling or parent route. @@ -63,7 +74,7 @@ Creates a link to a different view based on a route instruction consisting of a syntax(ts js): `` syntax(dart): -``|`[routerLink]` +``|`routerLink` description: The provided class(es) will be added to the element when the routerLink becomes the current active route. @@ -73,14 +84,14 @@ syntax(ts): canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot - ): Observable | boolean { ... } + ): Observable|Promise|boolean { ... } } { path: ..., canActivate: [CanActivateGuard] }`|`CanActivate` syntax(js): `var CanActivateGuard = ng.core.Class({ canActivate: function(route, state) { - // return Observable boolean or boolean + // return Observable/Promise boolean or boolean } }); @@ -88,7 +99,7 @@ syntax(js): syntax(dart): `@CanActivate(() => ...)class MyComponent() {}`|`@CanActivate` description: -{@target js ts}An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean or a Observable that resolves a boolean{@endtarget} +{@target js ts}An interface for defining a class that the router should call first to determine if it should activate this component. Should return an Observable/Promise that resolves a boolean or a boolean{@endtarget} {@target dart}A component decorator defining a function that the router should call first to determine if it should activate this component. Should return a boolean or a future.{@endtarget} @cheatsheetItem @@ -98,14 +109,14 @@ syntax(ts): component: T, route: ActivatedRouteSnapshot, state: RouterStateSnapshot - ): Observable | boolean { ... } + ): Observable|Promise|boolean { ... } } { path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate` syntax(js): `var CanDeactivateGuard = ng.core.Class({ canDeactivate: function(component, route, state) { - // return Observable boolean or boolean + // return Observable/Promise boolean or boolean } }); @@ -113,10 +124,30 @@ syntax(js): syntax(dart): `routerCanDeactivate(nextInstruction, prevInstruction) { ... }`|`routerCanDeactivate` description: -{@target js ts}An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean or a Observable that resolves a boolean{@endtarget} +{@target js ts}An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return an Observable/Promise that resolves a boolean or a boolean{@endtarget} {@target dart} The router calls the routerCanDeactivate methods (if defined) of every component that would be removed after a navigation. The navigation proceeds if and only if all such methods return true or a future that completes successfully{@endtarget}. +@cheatsheetItem +syntax(ts): +`class CanActivateChildGuard implements CanActivateChild { + canActivateChild( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable|Promise|boolean { ... } +} + +{ path: ..., canActivateChild: [CanActivateGuard], children: ... }`|`CanActivateChild` +syntax(js): +`var CanActivateChildGuard = ng.core.Class({ + canActivateChild: function(route, state) { + // return Observable/Promise boolean or boolean + } +}); + +{ path: ..., canActivateChild: [CanActivateChildGuard], children: ... }`|`CanActivateChild` +description: +{@target js ts}An interface for defining a class that the router should call first to determine if it should activate the child route. Should return an Observable/Promise that resolves a boolean or a boolean{@endtarget} @cheatsheetItem syntax(ts): @@ -124,20 +155,40 @@ syntax(ts): resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot - ): Observable | any { ... } + ): Observable|Promise|any { ... } } { path: ..., resolve: [ResolveGuard] }`|`Resolve` syntax(js): `var ResolveGuard = ng.core.Class({ resolve: function(route, state) { - // return Observable value or value + // return Observable/Promise value or value } }); { path: ..., resolve: [ResolveGuard] }`|`Resolve` description: -{@target js ts}An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable that resolves a value{@endtarget} +{@target js ts}An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return an Observable/Promise that resolves a value or a value{@endtarget} + +@cheatsheetItem +syntax(ts): +`class CanLoadGuard implements CanLoad { + canLoad( + route: Route + ): Observable|Promise|boolean { ... } +} + +{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad` +syntax(js): +`var CanLoadGuard = ng.core.Class({ + canLoad: function(route) { + // return Observable/Promise boolean or boolean + } +}); + +{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad` +description: +{@target js ts}An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return an Observable/Promise that resolves a boolean or a boolean{@endtarget} @cheatsheetItem syntax(dart): @@ -171,4 +222,4 @@ description: syntax(dart): `routerOnDeactivate(nextInstruction, prevInstruction) { ... }`|`routerOnDeactivate` description: -{@target dart}Called before the directive is removed as the result of a route change. May return a future that pauses removing the directive until the future completes.{@endtarget} \ No newline at end of file +{@target dart}Called before the directive is removed as the result of a route change. May return a future that pauses removing the directive until the future completes.{@endtarget} diff --git a/modules/@angular/router/src/config.ts b/modules/@angular/router/src/config.ts index d05bd14bf6..75e5dc5aa8 100644 --- a/modules/@angular/router/src/config.ts +++ b/modules/@angular/router/src/config.ts @@ -9,6 +9,7 @@ import {Type} from '@angular/core'; import {Observable} from 'rxjs/Observable'; + /** * `Routes` is an array of route configurations. Each one has the following properties: * diff --git a/modules/@angular/router/src/interfaces.ts b/modules/@angular/router/src/interfaces.ts index c4e6b9ae8b..6135ec8903 100644 --- a/modules/@angular/router/src/interfaces.ts +++ b/modules/@angular/router/src/interfaces.ts @@ -22,34 +22,48 @@ import {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state'; * class CanActivateTeam implements CanActivate { * constructor(private permissions: Permissions, private currentUser: UserToken) {} * - * canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable { - * return this.permissions.canActivate(this.currentUser, this.route.params.id); + * canActivate( + * route: ActivatedRouteSnapshot, + * state: RouterStateSnapshot + * ): Observable|Promise|boolean { + * return this.permissions.canActivate(this.currentUser, route.params.id); * } * } * - * bootstrap(AppComponent, [ - * CanActivateTeam, - * - * provideRouter([{ - * path: 'team/:id', - * component: Team, - * canActivate: [CanActivateTeam] - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * canActivate: [CanActivateTeam] + * } + * ]) + * ], + * providers: [CanActivateTeam] + * }) * ``` * * You can also provide a function with the same signature instead of the class: * * ``` - * bootstrap(AppComponent, [ - * {provide: 'canActivateTeam', useValue: (route: ActivatedRouteSnapshot, state: - * RouterStateSnapshot) => true}, - * provideRouter([{ - * path: 'team/:id', - * component: Team, - * canActivate: ['canActivateTeam'] - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * canActivate: ['canActivateTeam'] + * } + * ]) + * ], + * providers: [ + * { + * provide: 'canActivateTeam', + * useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => true + * } + * ] + * }) * ``` * * @stable @@ -69,47 +83,58 @@ export interface CanActivate { * class CanActivateTeam implements CanActivate { * constructor(private permissions: Permissions, private currentUser: UserToken) {} * - * canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable - * { + * canActivateChild( + * route: ActivatedRouteSnapshot, + * state: RouterStateSnapshot + * ): Observable|Promise|boolean { * return this.permissions.canActivate(this.currentUser, route.params.id); * } * } * - * bootstrap(AppComponent, [ - * CanActivateTeam, - * - * provideRouter([ - * { - * path: 'root', - * canActivateChild: [CanActivateTeam], - * children: [ - * { - * path: 'team/:id', - * component: Team - * } - * ] - * } - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'root', + * canActivateChild: [CanActivateTeam], + * children: [ + * { + * path: 'team/:id', + * component: Team + * } + * ] + * } + * ]) + * ], + * providers: [CanActivateTeam] + * }) * ``` * * You can also provide a function with the same signature instead of the class: * * ``` - * bootstrap(AppComponent, [ - * {provide: 'canActivateTeam', useValue: (route: ActivatedRouteSnapshot, state: - * RouterStateSnapshot) => true}, - * provideRouter([ + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'root', + * canActivateChild: ['canActivateTeam'], + * children: [ + * { + * path: 'team/:id', + * component: Team + * } + * ] + * } + * ]) + * ], + * providers: [ * { - * path: 'root', - * canActivateChild: ['canActivateTeam'], - * children: [ - * { - * path: 'team/:id', - * component: Team - * } - * ] - * } - * ]); + * provide: 'canActivateTeam', + * useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => true + * } + * ] + * }) * ``` * * @stable @@ -127,37 +152,52 @@ export interface CanActivateChild { * * ``` * @Injectable() - * class CanDeactivateTeam implements CanDeactivate { + * class CanDeactivateTeam implements CanDeactivate { * constructor(private permissions: Permissions, private currentUser: UserToken) {} * - * canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable { + * canDeactivate( + * component: TeamComponent, + * route: ActivatedRouteSnapshot, + * state: RouterStateSnapshot + * ): Observable|Promise|boolean { * return this.permissions.canDeactivate(this.currentUser, route.params.id); * } * } * - * bootstrap(AppComponent, [ - * CanDeactivateTeam, - * - * provideRouter([{ - * path: 'team/:id', - * component: Team, - * canDeactivate: [CanDeactivateTeam] - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * canDeactivate: [CanDeactivateTeam] + * } + * ]) + * ], + * providers: [CanDeactivateTeam] + * }) * ``` * * You can also provide a function with the same signature instead of the class: * * ``` - * bootstrap(AppComponent, [ - * {provide: 'canDeactivateTeam', useValue: (route: ActivatedRouteSnapshot, state: - * RouterStateSnapshot) => true}, - * provideRouter([{ - * path: 'team/:id', - * component: Team, - * canActivate: ['canDeactivateTeam'] - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * canActivate: ['canDeactivateTeam'] + * } + * ]) + * ], + * providers: [ + * { + * provide: 'canDeactivateTeam', + * useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => true + * } + * ] + * }) * ``` * * @stable @@ -174,29 +214,56 @@ export interface CanDeactivate { * * ``` * @Injectable() - * class TeamResolver implements Resolve { + * class TeamResolver implements Resolve { * constructor(private backend: Backend) {} * - * resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable { - * return this.backend.fetchTeam(this.route.params.id); + * resolve( + * route: ActivatedRouteSnapshot, + * state: RouterStateSnapshot + * ): Observable|Promise|any { + * return this.backend.fetchTeam(route.params.id); * } * } * - * bootstrap(AppComponent, [ - * TeamResolver, - * - * provideRouter([{ - * path: 'team/:id', - * component: TeamCmp, - * resolve: { - * team: TeamResolver - * } - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * resolve: { + * team: TeamResolver + * } + * } + * ]) + * ], + * providers: [TeamResolver] + * }) * ``` * * You can also provide a function with the same signature instead of the class. * + * ``` + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * resolve: { + * team: 'teamResolver' + * } + * } + * ]) + * ], + * providers: [ + * { + * provide: 'teamResolver', + * useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => 'team' + * } + * ] + * }) + * ``` * @stable */ export interface Resolve { @@ -215,37 +282,51 @@ export interface Resolve { * class CanLoadTeamSection implements CanLoad { * constructor(private permissions: Permissions, private currentUser: UserToken) {} * - * canLoad(route: Route):Observable { + * canLoad(route: Route( + * route: Route + * ): Observable|Promise|boolean { * return this.permissions.canLoadChildren(this.currentUser, route); * } * } * - * bootstrap(AppComponent, [ - * CanLoadTeamSection, - * - * provideRouter([{ - * path: 'team/:id', - * component: Team, - * loadChildren: 'team.js', - * canLoad: [CanLoadTeamSection] - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * loadChildren: 'team.js', + * canLoad: [CanLoadTeamSection] + * } + * ]) + * ], + * providers: [CanLoadTeamSection] + * }) * ``` * * You can also provide a function with the same signature instead of the class: * * ``` - * bootstrap(AppComponent, [ - * {provide: 'canLoadTeamSection', useValue: (route: Route) => true}, - * provideRouter([{ - * path: 'team/:id', - * component: Team, - * loadChildren: 'team.js', - * canLoad: ['canLoadTeamSection'] - * }]) - * ]); + * @NgModule({ + * imports: [ + * RouterModule.forRoot([ + * { + * path: 'team/:id', + * component: TeamCmp, + * loadChildren: 'team.js', + * canLoad: ['canLoadTeamSection'] + * } + * ]) + * ], + * providers: [ + * { + * provide: 'canLoadTeamSection', + * useValue: (route: Route) => true + * } + * ] + * }) * ``` * * @stable */ -export interface CanLoad { canLoad(route: Route): Observable|Promise|boolean; } \ No newline at end of file +export interface CanLoad { canLoad(route: Route): Observable|Promise|boolean; } diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index 6adcc44aad..1347cfb879 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -40,12 +40,95 @@ declare var Zone: any; * @experimental */ export interface NavigationExtras { + /** + * Enables relative navigation from the current ActivatedRoute + * + * Configuration + * + * ``` + * [{ + * path: 'parent', + * component: ParentComponent, + * children: [ + * { + * path: 'list', + * component: ListComponent + * }, + * { + * path: 'child', + * component: ChildComponent + * } + * ] + * }] + * ``` + * + * Navigate to list route from child route + * + * ``` + * @Component({...}) + * class ChildComponent { + * constructor(private router: Router, private route: ActivatedRoute) {} + * + * go() { + * this.router.navigate('../list', { relativeTo: this.route }); + * } + * } + * ``` + */ relativeTo?: ActivatedRoute; + /** + * Sets query parameters to the URL + * + * ``` + * // Navigate to /results?page=1 + * this.router.navigate('/results', { queryParams: { page: 1 } }); + * ``` + */ queryParams?: Params; + /** + * Sets the hash fragment for the URL + * + * ``` + * // Navigate to /results#top + * this.router.navigate('/results', { fragment: 'top' }); + * ``` + */ fragment?: string; + /** + * Preserves the query parameters for the next navigation + * + * ``` + * // Preserve query params from /results?page=1 to /view?page=1 + * this.router.navigate('/view', { preserveQueryParams: true }); + * ``` + */ preserveQueryParams?: boolean; + /** + * Preserves the fragment for the next navigation + * + * ``` + * // Preserve fragment from /results#top to /view#top + * this.router.navigate('/view', { preserveFragment: true }); + * ``` + */ preserveFragment?: boolean; + /** + * Navigates without pushing a new state into history + * + * ``` + * // Navigate silently to /view + * this.router.navigate('/view', { skipLocationChange: true }); + * ``` + */ skipLocationChange?: boolean; + /** + * Navigates while replacing the current state in history + * + * ``` + * // Navigate to /view + * this.router.navigate('/view', { replaceUrl: true }); + * ``` + */ replaceUrl?: boolean; } diff --git a/modules/@angular/router/src/router_module.ts b/modules/@angular/router/src/router_module.ts index 2b10e7847b..120ded2235 100644 --- a/modules/@angular/router/src/router_module.ts +++ b/modules/@angular/router/src/router_module.ts @@ -66,7 +66,7 @@ export const ROUTER_PROVIDERS: any[] = [ * bootstrap(AppCmp, {imports: [RouterModule.forRoot(ROUTES)]}); * ``` * - * For lazy loaded modules it should be used as follows: + * For submodules and lazy loaded submodules it should be used as follows: * * ### Example * @@ -167,4 +167,4 @@ export function provideRouterInitializer() { useFactory: initialRouterNavigation, deps: [Router] }; -} \ No newline at end of file +}