diff --git a/modules/@angular/router/index.ts b/modules/@angular/router/index.ts
index 1edfa14028..b07a00926a 100644
--- a/modules/@angular/router/index.ts
+++ b/modules/@angular/router/index.ts
@@ -1,7 +1,7 @@
/**
* @module
* @description
- * Alternative implementation of the router. Experimental.
+ * Maps application URLs into application states, to support deep-linking and navigation.
*/
export {Router, RouterOutletMap} from './src/router';
@@ -15,4 +15,24 @@ export {ROUTER_PROVIDERS} from './src/router_providers';
import {RouterOutlet} from './src/directives/router_outlet';
import {RouterLink} from './src/directives/router_link';
+/**
+ * A list of directives. To use the router directives like {@link RouterOutlet} and
+ * {@link RouterLink}, add this to your `directives` array in the {@link View} decorator of your
+ * component.
+ *
+ * ```
+ * import {Component} from '@angular/core';
+ * import {ROUTER_DIRECTIVES, Routes} from '@angular/router-deprecated';
+ *
+ * @Component({directives: [ROUTER_DIRECTIVES]})
+ * @RouteConfig([
+ * {...},
+ * ])
+ * class AppCmp {
+ * // ...
+ * }
+ *
+ * bootstrap(AppCmp);
+ * ```
+ */
export const ROUTER_DIRECTIVES: any[] = /*@ts2dart_const*/[RouterOutlet, RouterLink];
diff --git a/modules/@angular/router/src/constants.ts b/modules/@angular/router/src/constants.ts
index 52ecd2e56e..0f0377abec 100644
--- a/modules/@angular/router/src/constants.ts
+++ b/modules/@angular/router/src/constants.ts
@@ -1 +1,5 @@
+/**
+ * Name of the default outlet outlet.
+ * @type {string}
+ */
export const DEFAULT_OUTLET_NAME = "__DEFAULT";
\ No newline at end of file
diff --git a/modules/@angular/router/src/directives/router_link.ts b/modules/@angular/router/src/directives/router_link.ts
index bb3d9e2343..3ed2da67e8 100644
--- a/modules/@angular/router/src/directives/router_link.ts
+++ b/modules/@angular/router/src/directives/router_link.ts
@@ -19,16 +19,49 @@ import {RouteSegment, UrlSegment, Tree} from '../segments';
import {isString, isArray, isPresent} from '../facade/lang';
import {ObservableWrapper} from '../facade/async';
+/**
+ * The RouterLink directive lets you link to specific parts of your app.
+ *
+ * Consider the following route configuration:
+
+ * ```
+ * @Routes([
+ * { path: '/user', component: UserCmp }
+ * ]);
+ * class MyComp {}
+ * ```
+ *
+ * When linking to this `User` route, you can write:
+ *
+ * ```
+ * link to user component
+ * ```
+ *
+ * RouterLink expects the value to be an array of path segments, followed by the params
+ * for that level of routing. For instance `['/team', {teamId: 1}, 'user', {userId: 2}]`
+ * means that we want to generate a link to `/team;teamId=1/user;userId=2`.
+ *
+ * The first segment name can be prepended with `/`, `./`, or `../`.
+ * If the segment begins with `/`, the router will look up the route from the root of the app.
+ * If the segment begins with `./`, or doesn't begin with a slash, the router will
+ * instead look in the current component's children for the route.
+ * And if the segment begins with `../`, the router will go up one segment in the url.
+ *
+ * See {@link Router.createUrlTree} for more information.
+ */
@Directive({selector: '[routerLink]'})
export class RouterLink implements OnDestroy {
@Input() target: string;
private _commands: any[] = [];
private _subscription: any;
+ // the url displayed on the anchor element.
@HostBinding() href: string;
@HostBinding('class.router-link-active') isActive: boolean = false;
constructor(@Optional() private _routeSegment: RouteSegment, private _router: Router) {
+ // because auxiliary links take existing primary and auxiliary routes into account,
+ // we need to update the link whenever params or other routes change.
this._subscription =
ObservableWrapper.subscribe(_router.changes, (_) => { this._updateTargetUrlAndHref(); });
}
@@ -48,6 +81,7 @@ export class RouterLink implements OnDestroy {
@HostListener("click")
onClick(): boolean {
+ // If no target, or if target is _self, prevent default browser behavior
if (!isString(this.target) || this.target == '_self') {
this._router.navigate(this._commands, this._routeSegment);
return false;
diff --git a/modules/@angular/router/src/directives/router_outlet.ts b/modules/@angular/router/src/directives/router_outlet.ts
index 242d37facc..2ce7da5964 100644
--- a/modules/@angular/router/src/directives/router_outlet.ts
+++ b/modules/@angular/router/src/directives/router_outlet.ts
@@ -13,6 +13,21 @@ import {RouterOutletMap} from '../router';
import {DEFAULT_OUTLET_NAME} from '../constants';
import {isPresent, isBlank} from '../facade/lang';
+/**
+ * A router outlet is a placeholder that Angular dynamically fills based on the application's route.
+ *
+ * ## Use
+ *
+ * ```
+ *
+ * ```
+ *
+ * Outlets can be named.
+ *
+ * ```
+ *
+ * ```
+ */
@Directive({selector: 'router-outlet'})
export class RouterOutlet {
private _loaded: ComponentRef;
@@ -28,10 +43,19 @@ export class RouterOutlet {
this._loaded = null;
}
+ /**
+ * Returns the loaded component.
+ */
get loadedComponent(): Object { return isPresent(this._loaded) ? this._loaded.instance : null; }
+ /**
+ * Returns true is the outlet is not empty.
+ */
get isLoaded(): boolean { return isPresent(this._loaded); }
+ /**
+ * Called by the Router to instantiate a new component.
+ */
load(factory: ComponentFactory, providers: ResolvedReflectiveProvider[],
outletMap: RouterOutletMap): ComponentRef {
this.outletMap = outletMap;
diff --git a/modules/@angular/router/src/interfaces.ts b/modules/@angular/router/src/interfaces.ts
index c09b38df5f..54667579a2 100644
--- a/modules/@angular/router/src/interfaces.ts
+++ b/modules/@angular/router/src/interfaces.ts
@@ -1,10 +1,26 @@
import {RouteSegment, Tree, RouteTree} from './segments';
+/**
+ * Defines route lifecycle method `routerOnActivate`, which is called by the router at the end of a
+ * successful route navigation.
+ *
+ * The `routerOnActivate` hook is called with the current and previous {@link RouteSegment}s of the
+ * component and with the corresponding route trees.
+ */
export interface OnActivate {
routerOnActivate(curr: RouteSegment, prev?: RouteSegment, currTree?: RouteTree,
prevTree?: RouteTree): void;
}
+/**
+ * Defines route lifecycle method `routerOnDeactivate`, which is called by the router before
+ * destroying a component as part of a route change.
+ *
+ * The `routerOnDeactivate` hook is called with two {@link RouteTree}s, representing the current
+ * and the future state of the application.
+ *
+ * `routerOnDeactivate` must return a promise. The route change will wait until the promise settles.
+ */
export interface CanDeactivate {
routerCanDeactivate(currTree?: RouteTree, futureTree?: RouteTree): Promise;
}
\ No newline at end of file
diff --git a/modules/@angular/router/src/link.ts b/modules/@angular/router/src/link.ts
index a2d05ae0c9..f79105bd4c 100644
--- a/modules/@angular/router/src/link.ts
+++ b/modules/@angular/router/src/link.ts
@@ -3,6 +3,7 @@ import {isBlank, isPresent, isString, isStringMap} from './facade/lang';
import {BaseException} from './facade/exceptions';
import {ListWrapper} from './facade/collection';
+// TODO: vsavkin: should reuse segments
export function link(segment: RouteSegment, routeTree: RouteTree, urlTree: UrlTree, commands: any[]): UrlTree {
if (commands.length === 0) return urlTree;
diff --git a/modules/@angular/router/src/metadata/decorators.dart b/modules/@angular/router/src/metadata/decorators.dart
index b230a6c4c0..5f4dce731d 100644
--- a/modules/@angular/router/src/metadata/decorators.dart
+++ b/modules/@angular/router/src/metadata/decorators.dart
@@ -3,6 +3,11 @@ library angular.alt_router.decorators;
import 'metadata.dart';
export 'metadata.dart';
+/**
+ * Defines routes for a given component.
+ *
+ * It takes an array of {@link RouteMetadata}s.
+ */
class Routes extends RoutesMetadata {
const Routes(List routes): super(routes);
}
\ No newline at end of file
diff --git a/modules/@angular/router/src/metadata/decorators.ts b/modules/@angular/router/src/metadata/decorators.ts
index 63353c5b8b..581d7e6024 100644
--- a/modules/@angular/router/src/metadata/decorators.ts
+++ b/modules/@angular/router/src/metadata/decorators.ts
@@ -1,7 +1,19 @@
import {RoutesMetadata, RouteMetadata} from "./metadata";
import {makeDecorator} from '../core_private';
+
+/**
+ * Defines routes for a given component.
+ *
+ * It takes an array of {@link RouteMetadata}s.
+ */
export interface RoutesFactory {
(routes: RouteMetadata[]): any;
new (routes: RouteMetadata[]): RoutesMetadata;
}
+
+/**
+ * Defines routes for a given component.
+ *
+ * It takes an array of {@link RouteMetadata}s.
+ */
export var Routes: RoutesFactory = makeDecorator(RoutesMetadata);
diff --git a/modules/@angular/router/src/metadata/metadata.ts b/modules/@angular/router/src/metadata/metadata.ts
index 18d3f64c66..fc6263c648 100644
--- a/modules/@angular/router/src/metadata/metadata.ts
+++ b/modules/@angular/router/src/metadata/metadata.ts
@@ -1,12 +1,34 @@
import {Type} from '@angular/core';
import {stringify} from "../facade/lang";
+/**
+ * Information about a route.
+ *
+ * It has the following properties:
+ * - `path` is a string that uses the route matcher DSL.
+ * - `component` a component type.
+ *
+ * ### Example
+ * ```
+ * import {Routes} from '@angular/router';
+ *
+ * @Routes([
+ * {path: '/home', component: HomeCmp}
+ * ])
+ * class MyApp {}
+ * ```
+ *
+ * @ts2dart_const
+ */
export abstract class RouteMetadata {
abstract get path(): string;
abstract get component(): Type;
}
-/* @ts2dart_const */
+/**
+ * See {@link RouteMetadata} for more information.
+ * @ts2dart_const
+ */
export class Route implements RouteMetadata {
path: string;
component: Type;
@@ -17,7 +39,12 @@ export class Route implements RouteMetadata {
toString(): string { return `@Route(${this.path}, ${stringify(this.component)})`; }
}
-/* @ts2dart_const */
+/**
+ * Defines routes for a given component.
+ *
+ * It takes an array of {@link RouteMetadata}s.
+ * @ts2dart_const
+ */
export class RoutesMetadata {
constructor(public routes: RouteMetadata[]) {}
toString(): string { return `@Routes(${this.routes})`; }
diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts
index e729aaecc3..6e51b7e7fa 100644
--- a/modules/@angular/router/src/router.ts
+++ b/modules/@angular/router/src/router.ts
@@ -25,18 +25,30 @@ import {
import {hasLifecycleHook} from './lifecycle_reflector';
import {DEFAULT_OUTLET_NAME} from './constants';
+/**
+ * @internal
+ */
export class RouterOutletMap {
/** @internal */
_outlets: {[name: string]: RouterOutlet} = {};
registerOutlet(name: string, outlet: RouterOutlet): void { this._outlets[name] = outlet; }
}
+/**
+ * The `Router` is responsible for mapping URLs to components.
+ *
+ * You can see the state of the router by inspecting the read-only fields `router.urlTree`
+ * and `router.routeTree`.
+ */
export class Router {
private _prevTree: RouteTree;
private _urlTree: UrlTree;
private _locationSubscription: any;
private _changes: EventEmitter = new EventEmitter();
+ /**
+ * @internal
+ */
constructor(private _rootComponent: Object, private _rootComponentType: Type,
private _componentResolver: ComponentResolver,
private _urlSerializer: RouterUrlSerializer,
@@ -46,18 +58,94 @@ export class Router {
this.navigateByUrl(this._location.path());
}
+ /**
+ * Returns the current url tree.
+ */
get urlTree(): UrlTree { return this._urlTree; }
+ /**
+ * Returns the current route tree.
+ */
+ get routeTree(): RouteTree { return this._prevTree; }
+
+ /**
+ * An observable or url changes from the router.
+ */
+ get changes(): Observable { return this._changes; }
+
+ /**
+ * Navigate based on the provided url. This navigation is always absolute.
+ *
+ * ### Usage
+ *
+ * ```
+ * router.navigateByUrl("/team/33/user/11");
+ * ```
+ */
navigateByUrl(url: string): Promise {
return this._navigate(this._urlSerializer.parse(url));
}
+ /**
+ * Navigate based on the provided array of commands and a starting point.
+ * If no segment is provided, the navigation is absolute.
+ *
+ * ### Usage
+ *
+ * ```
+ * router.navigate(['team', 33, 'team', '11], segment);
+ * ```
+ */
navigate(commands: any[], segment?: RouteSegment): Promise {
return this._navigate(this.createUrlTree(commands, segment));
}
+ /**
+ * @internal
+ */
dispose(): void { ObservableWrapper.dispose(this._locationSubscription); }
+ /**
+ * Applies an array of commands to the current url tree and creates
+ * a new url tree.
+ *
+ * When given a segment, applies the given commands starting from the segment.
+ * When not given a segment, applies the given command starting from the root.
+ *
+ * ### Usage
+ *
+ * ```
+ * // create /team/33/user/11
+ * router.createUrlTree(['/team', 33, 'user', 11]);
+ *
+ * // create /team/33;expand=true/user/11
+ * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
+ *
+ * // you can collapse static fragments like this
+ * router.createUrlTree(['/team/33/user', userId]);
+ *
+ * // assuming the current url is `/team/33/user/11` and the segment points to `user/11`
+ *
+ * // navigate to /team/33/user/11/details
+ * router.createUrlTree(['details'], segment);
+ *
+ * // navigate to /team/33/user/22
+ * router.createUrlTree(['../22'], segment);
+ *
+ * // navigate to /team/44/user/22
+ * router.createUrlTree(['../../team/44/user/22'], segment);
+ * ```
+ */
+ createUrlTree(commands: any[], segment?: RouteSegment): UrlTree {
+ let s = isPresent(segment) ? segment : this._prevTree.root;
+ return link(s, this._prevTree, this.urlTree, commands);
+ }
+
+ /**
+ * Serializes a {@link UrlTree} into a string.
+ */
+ serializeUrl(url: UrlTree): string { return this._urlSerializer.serialize(url); }
+
private _createInitialTree(): RouteTree {
let root = new RouteSegment([new UrlSegment("", {}, null)], {}, DEFAULT_OUTLET_NAME,
this._rootComponentType, null);
@@ -84,17 +172,6 @@ export class Router {
});
});
}
-
- createUrlTree(commands: any[], segment?: RouteSegment): UrlTree {
- let s = isPresent(segment) ? segment : this._prevTree.root;
- return link(s, this._prevTree, this.urlTree, commands);
- }
-
- serializeUrl(url: UrlTree): string { return this._urlSerializer.serialize(url); }
-
- get changes(): Observable { return this._changes; }
-
- get routeTree(): RouteTree { return this._prevTree; }
}
diff --git a/modules/@angular/router/src/router_providers.ts b/modules/@angular/router/src/router_providers.ts
index 1dfb6a3c7b..3bc15761ab 100644
--- a/modules/@angular/router/src/router_providers.ts
+++ b/modules/@angular/router/src/router_providers.ts
@@ -2,6 +2,28 @@ import {ROUTER_PROVIDERS_COMMON} from './router_providers_common';
import {BrowserPlatformLocation} from '@angular/platform-browser';
import {PlatformLocation} from '@angular/common';
+/**
+ * A list of {@link Provider}s. To use the router, you must add this to your application.
+ *
+ * ```
+ * import {Component} from '@angular/core';
+ * import {
+ * ROUTER_DIRECTIVES,
+ * ROUTER_PROVIDERS,
+ * Routes
+ * } from '@angular/router';
+ *
+ * @Component({directives: [ROUTER_DIRECTIVES]})
+ * @Routes([
+ * {...},
+ * ])
+ * class AppCmp {
+ * // ...
+ * }
+ *
+ * bootstrap(AppCmp, [ROUTER_PROVIDERS]);
+ * ```
+ */
export const ROUTER_PROVIDERS: any[] = /*@ts2dart_const*/[
ROUTER_PROVIDERS_COMMON,
/*@ts2dart_Provider*/ {provide: PlatformLocation, useClass: BrowserPlatformLocation},
diff --git a/modules/@angular/router/src/router_providers_common.ts b/modules/@angular/router/src/router_providers_common.ts
index b3822ef38c..429201f4f7 100644
--- a/modules/@angular/router/src/router_providers_common.ts
+++ b/modules/@angular/router/src/router_providers_common.ts
@@ -5,6 +5,9 @@ import {RouterUrlSerializer, DefaultRouterUrlSerializer} from './router_url_seri
import {ApplicationRef} from '@angular/core';
import {BaseException} from '@angular/core';
+/**
+ * The Platform agnostic ROUTER PROVIDERS
+ */
export const ROUTER_PROVIDERS_COMMON: any[] = /*@ts2dart_const*/[
RouterOutletMap,
/*@ts2dart_Provider*/ {provide: RouterUrlSerializer, useClass: DefaultRouterUrlSerializer},
diff --git a/modules/@angular/router/src/router_url_serializer.ts b/modules/@angular/router/src/router_url_serializer.ts
index ada4462f3d..1d05564a95 100644
--- a/modules/@angular/router/src/router_url_serializer.ts
+++ b/modules/@angular/router/src/router_url_serializer.ts
@@ -2,11 +2,24 @@ import {UrlSegment, Tree, TreeNode, rootNode, UrlTree} from './segments';
import {BaseException} from '@angular/core';
import {isBlank, isPresent, RegExpWrapper} from './facade/lang';
+/**
+ * Defines a way to serialize/deserialize a url tree.
+ */
export abstract class RouterUrlSerializer {
+ /**
+ * Parse a url into a {@Link UrlTree}
+ */
abstract parse(url: string): UrlTree;
+
+ /**
+ * Converts a {@Link UrlTree} into a url
+ */
abstract serialize(tree: UrlTree): string;
}
+/**
+ * A default implementation of the serialization.
+ */
export class DefaultRouterUrlSerializer extends RouterUrlSerializer {
parse(url: string): UrlTree {
let root = new _UrlParser().parse(url);