diff --git a/modules/angular2/src/router/hash_location_strategy.ts b/modules/angular2/src/router/hash_location_strategy.ts index 25e2c24a99..5c25a1b9aa 100644 --- a/modules/angular2/src/router/hash_location_strategy.ts +++ b/modules/angular2/src/router/hash_location_strategy.ts @@ -3,6 +3,45 @@ import {Injectable} from 'angular2/src/core/di'; import {LocationStrategy} from './location_strategy'; import {EventListener, History, Location} from 'angular2/src/core/facade/browser'; +/** + * `HashLocationStrategy` is a {@link LocationStrategy} used to configure the + * {@link Location} service to represent its state in the + * [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) + * of the browser's URL. + * + * `HashLocationStrategy` is the default binding for {@link LocationStrategy} + * provided in {@link routerBindings} and {@link ROUTER_BINDINGS}. + * + * For instance, if you call `location.go('/foo')`, the browser's URL will become + * `example.com#/foo`. + * + * ## Example + * + * ``` + * import {Component, View} from 'angular2/angular2'; + * import { + * ROUTER_DIRECTIVES, + * routerBindings, + * RouteConfig, + * Location + * } from 'angular2/router'; + * + * @Component({...}) + * @View({directives: [ROUTER_DIRECTIVES]}) + * @RouteConfig([ + * {...}, + * ]) + * class AppCmp { + * constructor(location: Location) { + * location.go('/foo'); + * } + * } + * + * bootstrap(AppCmp, [ + * routerBindings(AppCmp) // includes binding to HashLocationStrategy + * ]); + * ``` + */ @Injectable() export class HashLocationStrategy extends LocationStrategy { private _location: Location; diff --git a/modules/angular2/src/router/location.ts b/modules/angular2/src/router/location.ts index 49c3f5a8aa..9bff5a80ba 100644 --- a/modules/angular2/src/router/location.ts +++ b/modules/angular2/src/router/location.ts @@ -5,17 +5,78 @@ import {isBlank} from 'angular2/src/core/facade/lang'; import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions'; import {OpaqueToken, Injectable, Optional, Inject} from 'angular2/src/core/di'; +/** + * The `APP_BASE_HREF` token represents the base href to be used with the + * {@link PathLocationStrategy}. + * + * If you're using {@link PathLocationStrategy}, you must provide a binding to a string + * representing the URL prefix that should be preserved when generating and recognizing + * URLs. + * + * ## Example + * + * ``` + * import {Component, View} from 'angular2/angular2'; + * import {ROUTER_DIRECTIVES, routerBindings, RouteConfig} from 'angular2/router'; + * + * @Component({...}) + * @View({directives: [ROUTER_DIRECTIVES]}) + * @RouteConfig([ + * {...}, + * ]) + * class AppCmp { + * // ... + * } + * + * bootstrap(AppCmp, [ + * routerBindings(AppCmp), + * PathLocationStrategy, + * bind(APP_BASE_HREF).toValue('/my/app') + * ]); + * ``` + */ export const APP_BASE_HREF: OpaqueToken = CONST_EXPR(new OpaqueToken('appBaseHref')); /** - * This is the service that an application developer will directly interact with. + * `Location` is a service that applications can use to interact with a browser's URL. + * Depending on which {@link LocationStrategy} is used, `Location` will either persist + * to the URL's path or the URL's hash segment. * - * Responsible for normalizing the URL against the application's base href. + * Note: it's better to use {@link Router#navigate} service to trigger route changes. Use + * `Location` only if you need to interact with or create normalized URLs outside of + * routing. + * + * `Location` is responsible for normalizing the URL against the application's base href. * A normalized URL is absolute from the URL host, includes the application's base href, and has no * trailing slash: * - `/my/app/user/123` is normalized * - `my/app/user/123` **is not** normalized * - `/my/app/user/123/` **is not** normalized + * + * ## Example + * + * ``` + * import {Component, View} from 'angular2/angular2'; + * import { + * ROUTER_DIRECTIVES, + * routerBindings, + * RouteConfig, + * Location + * } from 'angular2/router'; + * + * @Component({...}) + * @View({directives: [ROUTER_DIRECTIVES]}) + * @RouteConfig([ + * {...}, + * ]) + * class AppCmp { + * constructor(location: Location) { + * location.go('/foo'); + * } + * } + * + * bootstrap(AppCmp, [routerBindings(AppCmp)]); + * ``` */ @Injectable() export class Location { @@ -36,12 +97,23 @@ export class Location { (_) => { ObservableWrapper.callNext(this._subject, {'url': this.path(), 'pop': true}); }); } + /** + * Returns the normalized URL path. + */ path(): string { return this.normalize(this.platformStrategy.path()); } + /** + * Given a string representing a URL, returns the normalized URL path. + */ normalize(url: string): string { return stripTrailingSlash(_stripBaseHref(this._baseHref, stripIndexHtml(url))); } + /** + * Given a string representing a URL, returns the normalized URL path. + * If the given URL doesn't begin with a leading slash (`'/'`), this method adds one + * before normalizing. + */ normalizeAbsolutely(url: string): string { if (!url.startsWith('/')) { url = '/' + url; @@ -49,15 +121,28 @@ export class Location { return stripTrailingSlash(_addBaseHref(this._baseHref, url)); } + /** + * Changes the browsers URL to the normalized version of the given URL, and pushes a + * new item onto the platform's history. + */ go(url: string): void { var finalUrl = this.normalizeAbsolutely(url); this.platformStrategy.pushState(null, '', finalUrl); } + /** + * Navigates forward in the platform's history. + */ forward(): void { this.platformStrategy.forward(); } + /** + * Navigates back in the platform's history. + */ back(): void { this.platformStrategy.back(); } + /** + * Subscribe to the platform's `popState` events. + */ subscribe(onNext: (value: any) => void, onThrow: (exception: any) => void = null, onReturn: () => void = null): void { ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn); diff --git a/modules/angular2/src/router/location_strategy.ts b/modules/angular2/src/router/location_strategy.ts index 4643ff02e2..84d5798e1e 100644 --- a/modules/angular2/src/router/location_strategy.ts +++ b/modules/angular2/src/router/location_strategy.ts @@ -4,6 +4,22 @@ function _abstract() { return new BaseException('This method is abstract'); } +/** + * `LocationStrategy` is responsible for representing and reading route state + * from the the browser's URL. Angular provides two strategies: + * {@link HashLocationStrategy} (default) and {@link PathLocationStrategy}. + * + * This is used under the hood of the {@link Location} service. + * + * Applications should use the {@link Router} or {@link Location} services to + * interact with application route state. + * + * For instance, {@link HashLocationStrategy} produces URLs like + * `http://example.com#/foo`, and {@link PathLocationStrategy} produces + * `http://example.com/foo` as an equivalent URL. + * + * See these two classes for more. + */ export class LocationStrategy { path(): string { throw _abstract(); } pushState(ctx: any, title: string, url: string): void { throw _abstract(); } diff --git a/modules/angular2/src/router/path_location_strategy.ts b/modules/angular2/src/router/path_location_strategy.ts index 42525a4032..7d634d33b1 100644 --- a/modules/angular2/src/router/path_location_strategy.ts +++ b/modules/angular2/src/router/path_location_strategy.ts @@ -3,6 +3,52 @@ import {Injectable} from 'angular2/src/core/di'; import {EventListener, History, Location} from 'angular2/src/core/facade/browser'; import {LocationStrategy} from './location_strategy'; +/** + * `PathLocationStrategy` is a {@link LocationStrategy} used to configure the + * {@link Location} service to represent its state in the + * [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the + * browser's URL. + * + * If you're using `PathLocationStrategy`, you must provide a binding for + * {@link APP_BASE_HREF} to a string representing the URL prefix that should + * be preserved when generating and recognizing URLs. + * + * For instance, if you provide an `APP_BASE_HREF` of `'/my/app'` and call + * `location.go('/foo')`, the browser's URL will become + * `example.com/my/app/foo`. + * + * ## Example + * + * ``` + * import {Component, View, bind} from 'angular2/angular2'; + * import { + * APP_BASE_HREF + * ROUTER_DIRECTIVES, + * routerBindings, + * RouteConfig, + * Location, + * LocationStrategy, + * PathLocationStrategy + * } from 'angular2/router'; + * + * @Component({...}) + * @View({directives: [ROUTER_DIRECTIVES]}) + * @RouteConfig([ + * {...}, + * ]) + * class AppCmp { + * constructor(location: Location) { + * location.go('/foo'); + * } + * } + * + * bootstrap(AppCmp, [ + * routerBindings(AppCmp), + * bind(LocationStrategy).toClass(PathLocationStrategy), + * bind(APP_BASE_HREF).toValue('/my/app') + * ]); + * ``` + */ @Injectable() export class PathLocationStrategy extends LocationStrategy { private _location: Location;