+ `
+ // #enddocregion template
+})
+export class HeroListComponent implements OnInit {
+ public heroes: Hero[];
+ public selectedHero: Hero;
+
+ // #docregion ctor
+ constructor(
+ private _router: Router,
+ private _service: HeroService) { }
+ // #enddocregion ctor
+
+ ngOnInit() {
+ this._service.getHeroes().then(heroes => this.heroes = heroes)
+ }
+ // #docregion select
+ onSelect(hero: Hero) {
+ this._router.navigate( ['HeroDetail', { id: hero.id }] );
+ }
+ // #enddocregion select
+}
+// #enddocregion
+
+/* A link parameters array
+// #docregion link-parameters-array
+['HeroDetail', { id: hero.id }] // {id: 15}
+// #enddocregion link-parameters-array
+*/
\ No newline at end of file
diff --git a/public/docs/_examples/router/ts/app/heroes/hero.service.ts b/public/docs/_examples/router/ts/app/heroes/hero.service.ts
new file mode 100644
index 0000000000..f85d353d2d
--- /dev/null
+++ b/public/docs/_examples/router/ts/app/heroes/hero.service.ts
@@ -0,0 +1,27 @@
+// #docregion
+import {Injectable} from 'angular2/core';
+
+export class Hero {
+ constructor(public id: number, public name: string) { }
+}
+
+@Injectable()
+export class HeroService {
+ getHeroes() { return heroesPromise; }
+
+ getHero(id: number | string) {
+ return heroesPromise
+ .then(heroes => heroes.filter(h => h.id === +id)[0]);
+ }
+}
+
+var HEROES = [
+ new Hero(11, 'Mr. Nice'),
+ new Hero(12, 'Narco'),
+ new Hero(13, 'Bombasto'),
+ new Hero(14, 'Celeritas'),
+ new Hero(15, 'Magneta'),
+ new Hero(16, 'RubberMan')
+];
+
+var heroesPromise = Promise.resolve(HEROES);
diff --git a/public/docs/_examples/router/ts/example-config.json b/public/docs/_examples/router/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/router/ts/index.1.html b/public/docs/_examples/router/ts/index.1.html
new file mode 100644
index 0000000000..c8b08122be
--- /dev/null
+++ b/public/docs/_examples/router/ts/index.1.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+ Router Sample
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
+
diff --git a/public/docs/_examples/router/ts/index.html b/public/docs/_examples/router/ts/index.html
new file mode 100644
index 0000000000..309ee443f4
--- /dev/null
+++ b/public/docs/_examples/router/ts/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+ Router Sample
+
+
+
+
+
+
+
+
+
+
+
+ loading...
+
+
+
+
diff --git a/public/docs/_examples/router/ts/plnkr.json b/public/docs/_examples/router/ts/plnkr.json
new file mode 100644
index 0000000000..741f87caa6
--- /dev/null
+++ b/public/docs/_examples/router/ts/plnkr.json
@@ -0,0 +1,12 @@
+{
+ "description": "Router",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1,2,3].*",
+ "!app/crisis-list.component.ts",
+ "!app/hero-list.component.ts",
+ "!app/crisis-center/add-crisis.component.ts"
+ ],
+ "tags": ["router"]
+}
\ No newline at end of file
diff --git a/public/docs/_examples/router/ts/styles.css b/public/docs/_examples/router/ts/styles.css
new file mode 100644
index 0000000000..bb2b2c9cd9
--- /dev/null
+++ b/public/docs/_examples/router/ts/styles.css
@@ -0,0 +1,36 @@
+/* #docregion */
+/* #docregion heroes */
+/* #docregion starter */
+h1 {color: #369; font-family: Arial, Helvetica, sans-serif; font-size: 250%;}
+h2 { color: #369; font-family: Arial, Helvetica, sans-serif; }
+h3 { color: #444; font-weight: lighter; }
+body { margin: 2em; }
+body, input[text], button { color: #888; font-family: Cambria, Georgia; }
+button {padding: 0.2em; font-size: 14px}
+
+ul {list-style-type: none; margin-left: 1em; padding: 0; width: 20em;}
+
+li { cursor: pointer; position: relative; left: 0; transition: all 0.2s ease; }
+li:hover {color: #369; background-color: #EEE; left: .2em;}
+
+/* route-link anchor tags */
+a {padding: 5px; text-decoration: none; font-family: Arial, Helvetica, sans-serif; }
+a:visited, a:link {color: #444;}
+a:hover {color: white; background-color: #1171a3; }
+a.router-link-active {color: white; background-color: #52b9e9; }
+
+/* #enddocregion starter */
+.selected { background-color: #EEE; color: #369; }
+
+.badge {
+ font-size: small;
+ color: white;
+ padding: 0.1em 0.7em;
+ background-color: #369;
+ line-height: 1em;
+ position: relative;
+ left: -1px;
+ top: -1px;
+}
+/* #enddocregion heroes */
+/* #enddocregion */
\ No newline at end of file
diff --git a/public/docs/_examples/template-syntax/ts/app/app.component.ts b/public/docs/_examples/template-syntax/ts/app/app.component.ts
index 31ed7ad6f8..27436547f2 100644
--- a/public/docs/_examples/template-syntax/ts/app/app.component.ts
+++ b/public/docs/_examples/template-syntax/ts/app/app.component.ts
@@ -122,7 +122,7 @@ export class AppComponent {
// #docregion setStyles2
setStyles2() {
return {
- // camelCase style properties works too
+ // camelCase style properties work too
fontStyle: this.canSave ? 'italic' : 'normal', // italic
fontWeight: !this.isUnchanged ? 'bold' : 'normal', // normal
fontSize: this.isSpecial ? 'x-large': 'smaller', // larger
diff --git a/public/docs/ts/latest/guide/_data.json b/public/docs/ts/latest/guide/_data.json
index 1a8f3c296e..adfa83188e 100644
--- a/public/docs/ts/latest/guide/_data.json
+++ b/public/docs/ts/latest/guide/_data.json
@@ -43,6 +43,11 @@
"intro": "Pipes transform displayed values within a template"
},
+ "router": {
+ "title": "Routing & Navigation",
+ "intro": "Discover the basics of screen navigation with the Angular 2 router"
+ },
+
"attribute-directives": {
"title": "Attribute Directives",
"intro": "Attribute directives attach behavior to elements."
diff --git a/public/docs/ts/latest/guide/glossary.jade b/public/docs/ts/latest/guide/glossary.jade
index c7b5cfb0fb..57b284b973 100644
--- a/public/docs/ts/latest/guide/glossary.jade
+++ b/public/docs/ts/latest/guide/glossary.jade
@@ -399,9 +399,21 @@
and taking other similar actions that cause the application to
replace one view with another.
- The [Angular router](./router.html) is a richly featured mechanism for configuring
- and managing the entire navigation process including the creation and destruction
+ The Angular [Component Router](./router.html) is a richly featured mechanism for configuring
+ and managing the entire view navigation process including the creation and destruction
of views.
+:marked
+ ## Routing Component
+.l-sub-section
+ :marked
+ A [Component](#component) with an attached router.
+
+ In most cases, the component became attached to a [router](#router) by means
+ of a `@RouterConfig` decorator that defined routes to views controlled by this component.
+
+ The component's template has a `RouterOutlet` element where it can display views produced by the router.
+
+ It likely has anchor tags or buttons with `RouterLink` directives that users can click to navigate.
.l-main-section
diff --git a/public/docs/ts/latest/guide/router-aux.jade b/public/docs/ts/latest/guide/router-aux.jade
new file mode 100644
index 0000000000..e2074c45ce
--- /dev/null
+++ b/public/docs/ts/latest/guide/router-aux.jade
@@ -0,0 +1,183 @@
+//
+ TODO: REVIVE AUX ROUTE MATERIAL WHEN THAT FEATURE WORKS AS EXPECTED
+
+
+ .l-main-section
+ :marked
+ ## Milestone #4: Auxiliary Routes
+ Auxiliary routes are routes that can be activated independently of the current
+ route. They are entirely optional, depending on your app needs.
+
+ For example, your application may have a modal that appears and this could
+ be an auxiliary route. The modal may have its own navigation needs, such as a slideshow
+ and that auxiliary route is able to manage the navigation stack independently of the
+ primary routes.
+
+ In our sample application, we also want to have a chat feature that allows people
+ the ability to have a live agent assist them. The chat window will have first an
+ initial route that contains a prompt to ask the visitor if they'd like to chat with
+ an agent. Once they initiate a chat, they go to a new route for the chat experience.
+
+ .alert.is-critical Make diagram of chat routes
+
+ :marked
+ In this auxiliary chat experience, it overlays the current screen and persists.
+ If you navigate from the Heros to Crisis Center, the chat auxiliary route remains
+ active and in view.
+
+ Therefore the auxiliary routing is truly independent of the other
+ routing. In most respects, an auxiliary route behaves the same outside of it is rendered
+ in its own outlet and modifies the url differently.
+
+ We'll look at how to setup an auxiliary route and considerations for when to use them.
+
+ ### Auxiliary Route Outlet
+ In order to get an auxiliary route, it needs a place to be rendered. So far the app has
+ a single `RouterOutet` that the rest of our routes are rendered into. Auxiliary routes need to
+ have their own `RouterOutlet`, and that is done by giving it a name attribute. Open the
+ `app.component.ts` file and let's add the new outlet to the template.
+ .alert.is-critical Should remove app.component.4.ts based example (next) when we know what's what
+ +_makeExample('router/ts/app/app.component.4.ts', 'chat-outlet', 'app/app.component.ts')
+ .alert.is-critical Should be able to project from app.component.ts like this
+ +_makeExample('router/ts/app/app.component.ts', 'template', 'app/app.component.ts (excerpt)')
+ :marked
+ The name of the outlet must be unique to the component. You could reuse the name across
+ different components, so you don't have to worry about collisions.
+
+ Here we give it a name of "chat", which will be used by the router when we setup our
+ route configs. The app component needs to know about this Auxiliary route, so we
+ import the `ChatComponent`, add a new ROUTE_NAME (`chat`),
+ and add a new 'Chat' route to the `ROUTES` in `app.routes.ts` (just below the redirect) .
+ +_makeExample('router/ts/app/routes.ts', null, 'app/routes.ts')
+ :marked
+ Look again at the 'Chat' route
+ +_makeExample('router/ts/app/routes.ts','chat-route')
+ :marked
+ You can see the route definition is nearly the same, except instead of `path` there is
+ an `aux`. The `aux` property makes this an Auxiliary route.
+
+ @TODO Explain how a named outlet is paired with an aux route.
+
+ The chat component defines its own routes just like the other components, even though
+ it is an Auxiliary route.
+
+ +_makeExample('router/ts/app/chat/routes.ts', null, 'app/chat/routes.ts')
+ :marked
+ Even though this is an Auxiliary route, you notice there is no difference in how we've
+ configured the route config for the primary chat component. The chat component also has
+ the `RouterOutlet` Directive in the template so the child components render inside of
+ the chat window.
+
+ In the chat components, we can use `RouterLink` to reference routes just the same as
+ a normal route. Since this is inside of an Auxiliary route, these relative links will
+ resolve within the chat component and not change the primary route (the Crisis Center or
+ Heros pages).
+
+ +_makeExample('router/ts/app/chat/chat-init.component.ts', 'chat-links')
+
+ :marked
+ When the chat component opens, it first initializes this template to ask the user if
+ they'd like to chat or not. If they agree, it takes them to the chat window where they
+ begin to send messages to the 'live' agent.
+
+ The behavior of the chat components may be interesting, but have no additional insights
+ for routing, except for the ability to deactivate an active Auxiliary route.
+
+ ### Exiting an Auxiliary Route
+
+ @TODO Figure out how to close/deactivate an aux route
+
+ ### Auxiliary Route URLs
+
+ Auxiliary Routes do modify the url using parens, like so.
+ code-example(format=".", language="bash").
+ localhost:3002/crisis-center(chat)/2(details)
+ :marked
+ This would be the url on a page where the user was viewing an item in the Crisis Center,
+ in this case the "Dragon Burning Cities" crisis, and the `(chat)` Auxiliary Route would
+ active and on the details child route.
+
+ ### Multiple Auxiliary Routes
+
+ There is no limit to how many Auxiliary Routes you have defined or active. There is probably
+ a practical limit where too much appears on the screen for a user, but you can have as many
+ Auxiliary Routes as you have named `RouteOutlet`s.
+
+ :marked
+ ### Auxiliary Route Summary
+
+ * Auxiliary routes are normal routes that are rendered outside of the primary `RouterOutlet`
+ * They must use a named `RouterOutlet` to render.
+ * Can be activated as long as the parent component is active.
+ * Links inside of child components are resolved against the aux parent component.
+ * Auxiliary routes are deactivated by @TODO?
+ * Routes are indicated in the url using parens.
+ * Multiple aux routes can be active at once.
+
+ ### Chat
+ The "Chat" feature area within the `chat` folder looks like this:
+ ```
+ app/
+ chat/
+ ├── chat-detail.component.ts
+ ├── chat-init.component.ts
+ ├── chat.component.ts
+ ├── chat.service.ts
+ └── routes.ts
+ ```
+ +_makeTabs(
+ `router/ts/app/chat/chat.component.ts,
+ router/ts/app/chat/routes.ts,
+ router/ts/app/chat/chat-init.component.ts,
+ router/ts/app/chat/chat-detail.component.ts,
+ router/ts/app/chat/chat.service.ts
+ `,
+ null,
+ `chat.component.ts,
+ chat/routes.ts,
+ chat-init.component.ts,
+ chat-detail.component.ts,
+ chat.service.ts,
+ `)
+
+
+ The following are styles extracted from `styles.css`
+ that only belong if/when we add chat back
+ ```
+ /* chat styles */
+ .chat {
+ position: fixed;
+ bottom: 0;
+ right: 20px;
+ border: 1px solid #1171a3;
+ width: 400px;
+ height: 300px;
+ }
+ .chat h2 {
+ background: #1171a3;
+ color: #fff;
+ margin: 0;
+ padding: 8px;
+ }
+ .chat .close {
+ float: right;
+ display: block;
+ padding: 0 10px;
+ cursor: pointer;
+ }
+ .chat .chat-content {
+ padding: 10px;
+ }
+ .chat .chat-messages {
+ height: 190px;
+ overflow-y: scroll;
+ }
+ .chat .chat-input {
+ border-top: 1px solid #ccc;
+ padding-top: 10px;
+ }
+ .chat .chat-input input {
+ width: 370px;
+ padding: 3px;
+ }
+ ```
diff --git a/public/docs/ts/latest/guide/router-old-doc.jade b/public/docs/ts/latest/guide/router-old-doc.jade
new file mode 100644
index 0000000000..67e9028757
--- /dev/null
+++ b/public/docs/ts/latest/guide/router-old-doc.jade
@@ -0,0 +1,724 @@
+.l-main-section
+
+ h2#section-route-use Using the Component Router
+ p There are three steps to setting up routing with Angular's Component Router
+ ol
+ li Install the Component Router
+ li Map paths to components
+ li Link to routes
+
+
+.l-main-section
+
+ h2#section-install-router Import the Component Router
+
+ p.
+ Create two files, index.html and app.ts, both at the root of the project:
+
+ pre.prettyprint.lang-bash
+ code.
+ touch index.html app.ts
+
+ p Your app directory should look something like:
+ pre.prettyprint.lang-bash
+ code.
+ app.ts
+ index.html
+ package.json
+ node_modules/
+ └── ...
+
+ p.
+ Because the component is an addition to the core, you must install Angular's Component Router into your app.
+ When using the angular2.dev.js bundle you have include the additional router.dev.js bundle.
+
+ p.
+ Add Angular and Component Router into your app by adding the relevant <script> tags into your
+ index.html:
+
+ //ANGULAR 1
+ pre.prettyprint.lang-html.is-angular1.is-hidden
+ code.
+ <!doctype html>
+ <html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <base href="/">
+ <title>My app</title>
+ </head>
+ <body ng-app="myApp" ng-controller="AppController as app">
+ <div ng-outlet></div>
+ <script src="/node_modules/angular/angular.js"></script>
+ <script src="/dist/router.es5.js"></script>
+ <script src="/app/app.js"></script>
+ </body>
+ </html>
+
+ pre.prettyprint.lang-html.is-angular2
+ code.
+ <!doctype html>
+ <html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <base href="/">
+ <title>My app</title>
+ </head>
+ <body ng-app="myApp" ng-controller="AppController as app">
+ <script src="https://jspm.io/system@0.16.js"></script>
+ <script src="https://code.angularjs.org/2.0.0-alpha.21/angular2.dev.js"></script>
+ <script src="https://code.angularjs.org/2.0.0-alpha.21/router.dev.js"></script>
+ <script>
+ System.import('main');
+ </script>
+ </body>
+ </html>
+
+
+ p.is-angular2.
+ Then you can add the router into your app by importing the Router module in your app.ts file:
+
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ import {Component, View, bootstrap} from 'angular2/angular2';
+ import {Router, RouterOutlet, RouterLink} from 'angular2/router';
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ // self-executing bundle deploys angular APIs on the window object.
+ window.angular;
+ // the router APIs are part of the router sub-object.
+ window.angular.router;
+
+ p.is-angular1.is-hidden.
+ This is a pretty typical angular app, except the ng-outlet directive. ng-outlet is like
+ ng-view; it's a placeholder for part of your app loaded dynamically based on the route configuration.
+
+ p.is-angular2.
+ This is the same as you've seen in the rest of Angular 2, except the router-outlet directive.
+ router-outlet is a placeholder for part of your app loaded dynamically based on the route configuration.
+
+ p So how do we configure the app? Let's open app.ts and find out. Add this to the file:
+
+ //ANGULAR 1
+ pre.prettyprint.lang-javascript.is-angular1.is-hidden
+ code.
+ angular.module('app', ['ngNewRouter'])
+ .controller('AppController', ['$router', AppController]);
+
+ AppController.$routeConfig = [
+ {path: '/', component: 'home' }
+ ];
+ function AppController ($router) {}
+
+ // ANGULAR 2
+ .code-box
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ import {Component, View, bootstrap} from 'angular2/angular2';
+ import {routerInjectables, RouterOutlet} from 'angular2/router';
+
+ import {HomeComp} from './components/home';
+
+ @Component({
+ selector: 'my-app'
+ })
+ @View({
+ template: '<router-outlet></router-outlet>',
+ directives: [RouterOutlet]
+ })
+ @RouteConfig([
+ {path: '/', component: HomeComp }
+ ])
+ class AppComp {}
+
+ bootstrap(AppComp, routerInjectables);
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ var HomeComp = function() {};
+ ...
+
+ var AppComp = function() {};
+ AppComp.annotations = [
+ new angular.ComponentAnnotation({
+ selector: 'my-app'
+ }),
+ new angular.ViewAnnotation({
+ template: '<router-outlet></router-outlet>',
+ directives: [angular.router.RouterOutlet]
+ }),
+ new angular.router.RouteConfigAnnotation([
+ {path: '/', component: HomeComp}
+ ])
+ ];
+
+ angular.bootstrap(AppComp, routerInjectables);
+
+
+ p.is-angular1.is-hidden.
+ The ngComponentRouter module provides a new service, $router. In the configuration, we map paths
+ to components. What's a component? Let's talk about that for a bit.
+
+ p.is-angular2.
+ The angular2/router module provides routerInjectables, which is an array of all of the services
+ you'll need to use the component router in your app.
+
+.l-main-section
+ h2#section-map-paths-to-components Map paths to components
+
+ //- TODO - Alex - would it make more sense to have some paragraph styles conditionalized like this??
+ p.angular1.is-hidden.
+ In Angular 1, a "routable component" is a template, plus a controller, plus a router. You can configure how to map
+ component names to controllers and templates in the $componentLoader service.
+
+ p.
+ A component's template can have "outlets," which are holes in the DOM for loading parts of your app based on the
+ route configuration and it can ask the DI system for an instance of Router. A component's router tells the component what to put
+ inside the outlets based on URL. The configuration maps routes to components for each outlet.
+
+ p Let's make a home component that our app can route to:
+
+ pre.prettyprint.lang-bash
+ code.
+ mkdir -p components/home
+ touch components/home/home.html components/home/home.js
+
+ p This creates our component directory and its corresponding files: a template and a JavaScript component.
+
+ p Let's open home.html and add some content:
+
+ pre.prettyprint.lang-html
+ code.
+ <h1>Hello {{home.name}}!</h1>
+
+ p.is-angular1.is-hidden.
+ Components use the "controller as" syntax, so if we want to access property name of the controller, we
+ write the binding as home.name.
+
+ p Let's make a controller:
+ //ANGULAR 1
+ pre.prettyprint.lang-javascript.is-angular1.is-hidden
+ code.
+ angular.module('app.home', [])
+ .controller('HomeController', [function () {
+ this.name = 'Friend';
+ }]);
+
+ // ANGULAR 2
+ .code-box
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ @Component({
+ selector: 'home-cmp'
+ })
+ @View({
+ template: 'Hello {{name}}'
+ })
+ export class HomeComponent {
+ name:string;
+ constructor() {
+ this.name = 'Friend';
+ }
+ }
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ function HomeComponent() {
+ this.name = 'Friend';
+ }
+
+ AppComponent.annotations = [
+ new angular.ComponentAnnotation({
+ selector: 'home-cmp'
+ }),
+ new angular.ViewAnnotation({
+ template: 'Hello {{name}}'
+ })
+ ];
+
+
+ p.is-angular1.is-hidden.
+ To wire this up, we need to add a <script> tag to our index.html:
+ pre.prettyprint.lang-html
+ code.
+ ...
+ <script src="./components/home/home.js"></script>
+
+ //ANGULAR 1
+ p.is-angular1.is-hidden.
+ And add the controller's module as a dependency to our main module in app.js:
+ pre.prettyprint.lang-javascript.is-angular1.is-hidden
+ code.
+ angular.module('app', ['ngNewRouter', 'app.home'])
+ .controller('AppController', ['$router', AppController]);
+ // ...
+
+ p.
+ To wire this up, we need to import the component into the rest of our app.
+ // ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ import {HomeComp} from './components/home';
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ // Use your favorite module system / bundler for ES5.
+
+
+ p If you load up the app, you should see Hello Friend!
+
+.l-main-section
+ h2#section-link-to-routes Link to routes
+
+ p Let's add another route and then link to it. This route will have a route parameter, id.
+
+ p In app.js:
+ //ANGULAR 1
+ pre.prettyprint.lang-javascript.is-hidden
+ code.
+ angular.module('app', ['ngNewRouter'])
+ .controller('AppController', ['$router', AppController]);
+ AppController.$routeConfig = [
+ { path: '/', component: 'home' },
+ { path: '/detail/:id', component: 'detail' }
+ ];
+ function AppController ($router) {}
+
+ // ANGULAR 2
+ .code-box
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ ...
+ @RouteConfig([
+ { path: '/', component: HomeComp },
+ { path: '/detail/:id', component: DetailComp }
+ ])
+ class AppComp {}
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ var AppComp = function() {};
+ AppComp.annotations = [
+ ...
+ new angular.router.RouteConfigAnnotation([
+ { path: '/', component: HomeComp}
+ { path: '/detail/:id', component: DetailComp }
+ ])
+ ];
+
+ angular.bootstrap(AppComp, routerInjectables);
+
+
+ p.
+ We can link to our detail component using the
+ router-linkng-link directive.
+ Add this to templateindex.html:
+
+ pre.prettyprint.lang-html.is-angular1.is-hidden.
+ code.
+ <body ng-app="myApp" ng-controller="AppController as app">
+ <a ng-link="detail({id: 5})">link to detail</a>
+ ...
+
+ pre.prettyprint.lang-html.is-angular2
+ code.
+ <a ng-link="detail({id: 5})">link to detail</a>
+
+ p This directive will generate an href and update the browser URL.
+
+ p We should also implement our detail component. Let's make these new files:
+
+ pre.prettyprint.lang-bash
+ code.
+ mkdir components/detail
+ touch components/detail/detail.html components/detail/detail.ts
+
+ p In detail.ts, we implement a controller that uses the id route parameter:
+
+ //ANGULAR 1
+ pre.prettyprint.lang-javascript.is-hidden
+ code.
+ angular.module('app.detail', ['ngNewRouter'])
+ .controller('DetailController', ['$routeParams', DetailController]);
+
+ function DetailController ($routeParams) {
+ this.id = $routeParams.id;
+ }
+
+ // ANGULAR 2
+ .code-box
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ @Component({
+ selector: 'detail-cmp'
+ })
+ @View({
+ template: 'User ID: {{id}}'
+ })
+ export class DetailComp {
+ id: string;
+ constructor(routeParams:RouteParams) {
+ this.id = routeParams.get('id');
+ }
+ }
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ function DetailComp(routeParams) {
+ this.id = routeParams.get('id');
+ }
+
+ DetailComp.annotations = [
+ new angular.ComponentAnnotation({
+ selector: 'detail-cmp'
+ }),
+ new angular.ViewAnnotation({
+ template: 'User ID: {{id}}'
+ })
+ ];
+
+ DetailComp.parameters = [[RouteParams]];
+
+
+ p.is-angular1.is-hidden.
+ And then we can display the id in our template by adding this to detail.html:
+
+ pre.prettyprint.lang-html.is-angular1.is-hidden
+ code.
+ <p>detail {{detail.id}}</p>
+
+ p.is-angular1.is-hidden.
+ Finally, we'd wire up the controller by adding a script tag and making our app module depend on
+ app.detail.
+
+
+.l-main-section
+
+ h2#section-configuring-the-router Configuring the Router
+
+ p.
+ Unlike other routing systems, Component Router maps URLs to components. A router takes an array of pairings like
+ this:
+
+ //ANGULAR 1
+ pre.prettyprint.lang-javascript.is-angular1.is-hidden
+ code.
+ //ES5
+ MyController.$routeConfig = [
+ { path: '/user', component: 'user' }
+ ];
+
+
+ //ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-javascript(data-name="typescript")
+ code.
+ @Component()
+ @View()
+ @RouteConfig([
+ { path: '/user', component: UserComponent }
+ ])
+ class MyComp {}
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ function MyComp() {};
+ MyComp.annotations = [
+ new angular.ComponentAnnotation({ ... }),
+ new angular.ViewAnnotation({ ... }),
+ new angular.router.RouteConfigAnnotation([
+ {path: '/', component: UserComponent}
+ ])
+
+
+ .l-sub-section
+ h3#section-sibling-outlets Sibling Outlets
+
+
+ p You can configure multiple outlets on the same path like this:
+
+ //ANGULAR 1
+ .codebox.is-angular1.is-hidden
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ //ES5
+ MyController.$routeConfig = [
+ { path: '/user',
+ components: {
+ master: 'userList',
+ detail: 'user'
+ } }
+ ];
+
+ pre.prettyprint.linenums.lang-html(data-name="html")
+ code.
+ //HTML
+ <div ng-outlet="master"></div>
+ <div ng-outlet="detail"></div>
+
+
+ //ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ //TypeScript
+ @Component({})
+ @View({
+ template:
+ `<div router-outlet="master"></div>
+ <div router-outlet="detail"></div>`,
+ directives: [RouterOutlet, RouterLink]
+ })
+ @RouteConfig({
+ path: '/user', components: {
+ master: UserListComp,
+ detail: UserComp
+ }
+ })
+ class MyComponent {}
+
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ function MyComponent() {};
+ MyComponent.annotations = [
+ new angular.ComponentAnnotation({ ... }),
+ new angular.ViewAnnotation({
+ template:
+ '<div router-outlet="master"></div>' +
+ '<div router-outlet="detail"></div>',
+ directives: [RouterOutlet]
+ }),
+ new angular.router.RouteConfigAnnotation([{
+ path: '/user', components: {
+ master: UserComponent,
+ detail: UserComp
+ }
+ }])
+ ];
+
+ p You can link to any sibling just as you normally would:
+
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-html.is-angular1.is-hidden
+ code.
+ //HTML
+ <p>These both link to the same view:</p>
+ <a ng-link="userList">link to userList</a>
+ <a ng-link="user">link to user component</a>
+
+ //ANGULAR 2
+ pre.prettyprint.linenums.lang-html.is-angular2
+ code.
+ //HTML
+ <p>These both link to the same view:</p>
+ <a router-link="userList">link to userList</a>
+ <a router-link="user">link to user component</a>
+
+
+ p Or, you can explicitly link to a outlet-component pair like this:
+
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-html.is-angular1.is-hidden
+ code.
+ //HTML
+ <p>These both link to the same view:</p>
+ <a ng-link="master:userList">link to userList</a>
+ <a ng-link="detail:user">link to user component</a>
+
+ //ANGULAR 2
+ pre.prettyprint.linenums.lang-html.is-angular2
+ code.
+ //HTML
+ <p>These both link to the same view:</p>
+ <a router-link="master:userList">link to userList</a>
+ <a router-link="detail:user">link to user component</a>
+
+ .l-sub-section
+ h3#section-redirecting-routes Redirecting routes
+
+ p You can use `redirectTo` for migrating to a new URL scheme and setting up default routes.
+
+ p.
+ For example, as specified below, when a user navigates to `/`, the URL changes to `/user` and the outlet
+ at that level loads the `user` component.
+
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-javascript.is-angular1.is-hidden(data-name="es5")
+ code.
+ //ES5
+ MyController.$routeConfig = [
+ { path: '/', redirectTo: '/user' },
+ { path: '/user', component: 'user' }
+ ];
+ function MyController() {}
+
+ //ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ //TypeScript
+ @Component({})
+ @View({
+ directives: [RouterOutlet]
+ })
+ @RouteConfig([
+ { path: '/', redirectTo: '/user' },
+ { path: '/user', component: UserComp }
+ ])
+ class MyComp {}
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ function MyComponent() {};
+ MyComponent.annotations = [
+ new angular.ComponentAnnotation({ ... }),
+ new angular.ViewAnnotation({
+ directives: [RouterOutlet]
+ }),
+ new angular.router.RouteConfigAnnotation([
+ { path: '/user', component: UserComp }
+ { path: '/', redirectTo: '/user' },
+ ])
+ ];
+
+
+ .l-sub-section
+ h3#section-aliases Aliases
+
+ p.
+ When linking to a route, you normally use the name of the component. You can also specify an alias to use
+ instead.
+
+ p Consider the following route configuration:
+
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-javascript.is-angular1.is-hidden(data-name="es5")
+ code.
+ //ES5
+ MyController.$routeConfig = [
+ { path: '/', component: 'user' }
+ ];
+
+ //ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ //TypeScript
+ @Component({
+ selector: 'my-comp'
+ })
+ @View({
+ directives: [RouterOutlet]
+ })
+ @RouteConfig([
+ { path: '/', component: UserComp }
+ ])
+ class MyComp {}
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ function MyComp() {};
+ MyComp.annotations = [
+ new angular.ComponentAnnotation({ ... }),
+ new angular.ViewAnnotation({
+ directives: [RouterOutlet]
+ }),
+ new angular.router.RouteConfigAnnotation([
+ { path: '/', component: UserComp }
+ ])
+ ];
+
+
+ p We can link to the route in our template with the name of the component:
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-html.is-angular1.is-hidden
+ code.
+ //HTML
+ <a ng-link="user">link to user component</a>
+
+ //ANGULAR 2
+ pre.prettyprint.linenums.lang-html
+ code.
+ //HTML
+ <a router-link="user">link to user component</a>
+
+ p Or, we can define an alias myUser like this:
+
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-javascript.is-angular1.is-hidden(data-name="es5")
+ code.
+ //ES5
+ MyController.$routeConfig = [
+ { path: '/', component: 'user', as: 'myUser' }
+ ];
+
+ //ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ //TypeScript
+ @Component()
+ @View()
+ @RouteConfig([
+ { path: '/', component: UserComp, as: 'myUser' }
+ ])
+ class MyComp {}
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ //ES5
+ //TODO: Need Angular 2 ES5 Example here
+
+
+ p And refer instead to the alias for the component in our template, with the same end-result:
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-html.is-angular1.is-hidden
+ code.
+ //HTML
+ <a ng-link="myUser">link to user component</a>
+
+ //ANGULAR 2
+ pre.prettyprint.linenums.lang-html
+ code.
+ //HTML
+ <a router-link="myUser">link to user component</a>
+
+
+ p.
+ This is especially useful when you have sibling components, but want to refer to an entire level of routing in
+ your controller. For example:
+
+ //ANGULAR 1
+ pre.prettyprint.linenums.lang-javascript.is-angular1.is-hidden(data-name="es5")
+ code.
+ //ES5
+ MyController.$routeConfig = [
+ { path: '/',
+ components: {
+ master: 'userList',
+ detail: 'user'
+ },
+ as: 'myUser'
+ }
+ ];
+
+ //ANGULAR 2
+ .code-box.is-angular2
+ pre.prettyprint.linenums.lang-typescript(data-name="typescript")
+ code.
+ //TypeScript
+ @RouteConfig([
+ { path: '/', components:
+ { master: UserListComp, detail: UserComp },
+ as: 'myUser' }
+ ])
+ pre.prettyprint.linenums.lang-javascript(data-name="es5")
+ code.
+ new angular.router.RouteConfigAnnotation([
+ { path: '/', components:
+ { master: UserListComp, detail: UserComp },
+ as: 'myUser' }
+ ])
+
+
+ //- TODO(btford): expand on this.
+ .l-sub-section
+ h3#dynamic-configuration Dynamic Configuration
+
+ p.is-angular2.
+ You can configure dynamic routing by asking the DI system for a Router.
+
+ p.is-angular1.is-hidden
+ You can configure dynamic routing by making a request for $router.
diff --git a/public/docs/ts/latest/guide/router.jade b/public/docs/ts/latest/guide/router.jade
index 2d23c624b4..c305310efc 100644
--- a/public/docs/ts/latest/guide/router.jade
+++ b/public/docs/ts/latest/guide/router.jade
@@ -1,9 +1,1043 @@
include ../../../../_includes/_util-fns
:marked
- # App Navigation with the Router
- It's coming soon!
+ In most applications, users navigate from one [view](./glossary.html#view) to the next
+ as they perform application tasks.
+
+ The browser is a familiar model of application navigation.
+ We enter a URL in the address bar and the browser navigates to a corresponding page.
+ We click links on the page and the browser navigates to a new page.
+ We click the browser's back and forward buttons and the browser navigates
+ backward and forward through the history of pages we've seen.
+
+ The Angular "**Component Router**" (AKA "the router") borrows from this model.
+ It can interpret a browser URL as an instruction
+ to navigate to a client-generated view and pass optional parameters along to the supporting view component
+ to help it decide what specific content to present.
+ We can bind the router to links on a page and it will navigate to
+ the appropriate application view when the user clicks a link.
+ We can navigate imperatively when the user clicks a button, selects from a drop box,
+ or in response to some other stimulus from any source. And the router logs activity
+ in the browser's history journal so the back and forward buttons work as well.
+
+ [Live Example](/resources/live-examples/router/ts/src/plnkr.html).
+.l-main-section
+:marked
+ ## The Basics
+ Let's begin with a few core concepts of the Component Router.
+ Then we can explore the details through a sequence of examples.
+
+ The **`Router`** is a service that presents a particular Component view for a given URL.
+ When the browser's URL changes, the router looks for a corresponding **`RouteDefinition`**
+ from which it can determine the Component to display.
+
+ A new router has no route definitions. We have to configure it.
+ The preferred way to configure the router is with a **`@RouteConfig`** [decorator](glossary.html#decorator)
+ applied to a host component.
+
+ In this example, we configure the top-level `AppComponent` with three route definitions
++makeExample('router/ts/app/app.component.2.ts', 'route-config', 'app.component.ts (excerpt)')(format=".")
+:marked
+
+.l-sub-section
+ :marked
+ There are several flavors of `RouteDefinition`.
+ The most common by far is the named **`Route`** which maps a URL path to a Component
+
+ The `name` field is the name of the `Route`. The name **must** be spelled in **PascalCase**.
+
+ The `:id` in the third route is a token for a route parameter. In a URL such as `/hero/42`, "42"
+ is the value of the `id` parameter. The corresponding `HeroDetailComponent`
+ will use that value to find and present the hero whose `id` is 42.
+ We'll learn more about route parameters later in this chapter.
+:marked
+ Now we know how the router gets its configuration.
+ When the browser URL for this application becomes `/heroes`,
+ the router finds the `RouteDefintion` named *Heroes* and then knows to display the `HeroListComponent`.
+
+ Display it where? It will display in a **`RouterOutlet`** that we've placed in the host view's HTML.
+code-example(format="", language="html").
+ <!-- Routed views go here -->
+ <router-outlet></router-outlet>
+:marked
+ Now we have routes configured and a place to render them, but
+ how do we navigate? The URL could arrive directly from the browser address bar.
+ But most of the time we navigate as a result of some user action such as the click of
+ an anchor tag.
+
+ In an anchor tag we bind a **`RouterLink`** Directive to a template expression that
+ returns an **array of route link parameters**. The router ultimately resolves that array
+ into a URL and a component view.
+
+ We see such bindings in the following `AppComponent` template:
++makeExample('router/ts/app/app.component.1.ts', 'template')(format=".")
+.l-sub-section
+ :marked
+ We're adding two anchor tags with `RouterLink` directives.
+ We bind each `RouterLink` to an array containing the string name of a route definition.
+ 'CrisisCenter' and 'Heroes' are the names of the `Routes` we configured above.
+
+ We'll learn to write more complex link expressions ... and why they are arrays ... later in the chapter.
+:marked
+ ### Let's summarize
+
+ The `@RouterConfig` configuration tied the `AppComponent` to a router configured with routes.
+ The component has a `RouterOutlet` where it can display views produced by the router.
+ It has `RouterLinks` that users can click to navigate via the router.
+
+ The `AppComponent` has become a ***Routing Component***, a component that can route.
+
+ Here are the key *Component Router* terms and their meanings:
+table
+ tr
+ th Router Part
+ th Meaning
+ tr
+ td Router
+ td.
+ Displays the application component for the active URL.
+ Manages navigation from one component to the next.
+ tr
+ td @RouteConfig
+ td.
+ Configures a router with RouteDefinitions, each mapping a URL path to a Component.
+ tr
+ td RouteDefinition
+ td.
+ Defines how the router should navigate to a Component based on a URL pattern.
+ tr
+ td Route
+ td.
+ The most common form of RouteDefinition consisting of a path, a route name,
+ and a component type.
+ tr
+ td RouterOutlet
+ td.
+ The directive (<router-outlet>) that marks where the router should display a view.
+ tr
+ td RouterLink
+ td.
+ The directive for binding a clickable HTML element to
+ a route. Clicking an anchor tag with a routerLink directive
+ that is bound to a Link Parameters Array triggers a navigation.
+ tr
+ td Link Parameters Array
+ td.
+ An array that the router inteprets into a routing instruction.
+ We can bind a RouterLink to that array or pass the array as an argument to
+ the Router.navigate method.
+:marked
+ We'll learn many more details in this chapter which covers
+
+ * configuring a router
+ * the link parameter arrays that propel router navigation
+ * navigating when the user clicks a data-bound link
+ * navigating under program control
+ * passing information in route parameters
+ * creating a child router with its own routes
+ * setting a default route (the *otherwise* option)
+ * asking the user's permission to leave before navigating to a new view using lifecycle events
+
+ We will proceed in phases marked by milestones.
+ Our first milestone is the ability to navigate between between two placeholder views.
+ At our last milestone, we'll have a modular, multi-view design with child routes.
+
+ We assume that you're already comfortable with the basic Angular 2 concepts and tools
+ we introduced in the [QuickStart](../quickstart.html) and
+ the [Tour of Heroes](../tutorial/) tutorial.
+
+ While there is a progression, this chapter is not a tutorial.
+ We discuss code and design decisions pertinent to routing and application design.
+ We gloss over everything else.
+
+ The full source is available in the [live example](/resources/live-examples/router/ts/src/plnkr.html).
+
+.callout.is-critical
+ header Route Link Syntax - Note to self
+ :marked
+ The tutorial approach won't be the best way to fully describe the link parameters array.
+
+ Create an appendix on route link syntax ... how the array is interpreted ... and
+ link to it at the appropriate time.
.l-main-section
:marked
- ## What's not to love?
\ No newline at end of file
+ ## The Sample Application
+ We have an application in mind as we move from milestone to milestone.
+ Our client is the Hero Employment Agency.
+ Heroes need work and The Agency finds Crises for them to solve.
+
+ The application has two main feature areas:
+ 1. A *Crisis Center* where we maintain the list of crises for assignment to heroes.
+ 1. A *Heroes* area where we maintain the list of heroes employed by The Agency.
+
+ Run the [live example](/resources/live-examples/router/ts/src/plnkr.html).
+ It opens in the *Crisis Center*. We'll come back to that.
+
+ Click the *Heroes* link. We're presented with a list of Heroes.
+figure.image-display
+ img(src='/resources/images/devguide/router/hero-list.png' alt="Hero List" width="250")
+:marked
+ We select one and the applications takes us to a hero editing screen.
+figure.image-display
+ img(src='/resources/images/devguide/router/hero-detail.png' alt="Crisis Center Detail" width="250")
+:marked
+ Our changes take affect immediately. We click the "Back" button and the
+ app returns us to the Heroes list.
+
+ We could have clicked the browser's back button instead.
+ That would have returned us to the Heroes List as well.
+ Angular app navigation updates the browser history as normal web navigation does.
+
+ Now click the *Crisis Center* link. We go to the *Crisis Center* and its list of ongoing crises.
+figure.image-display
+ img(src='/resources/images/devguide/router/crisis-center-list.png' alt="Crisis Center List" )
+:marked
+ We select one and the applications takes us to a crisis editing screen.
+figure.image-display
+ img(src='/resources/images/devguide/router/crisis-center-detail.png' alt="Crisis Center Detail")
+:marked
+ This is a bit different then the "Heroes Detail". We have two buttons, "Save" and "Cancel".
+ If we make a change and click "Save", we return to the *Crisis Center* and see our changes
+ reflected in the list. If we make a change and click "Cancel",
+ we return to the *Crisis Center* but this time our changes were discarded.
+
+ Now we click a crisis, make a change, and ***do not click either button***.
+ We click the browser back button instead. Up pops a modal dialog box.
+figure.image-display
+ img(src='/resources/images/devguide/router/confirm-dialog.png' alt="Confirm Dialog" width="300")
+:marked
+ We can say "OK" and lose our changes or click "Cancel" and continue editing.
+
+ The router supports a `CanDeactivate` lifecycle" method that gives us a chance to clean-up
+ or ask the user's permission before navigating away from the current view.
+
+ Let's see a quick demonstration of the workflow in action.
+
+figure.image-display
+ img(src='/resources/images/devguide/router/router-anim.gif' alt="App in action" )
+:marked
+ Here's a diagram of all application routing options:
+figure.image-display
+ img(src='/resources/images/devguide/router/complete-nav.png' alt="Navigation diagram" )
+:marked
+ This app illustrates the router features we'll cover in this chapter
+
+ * navigating to a component (*Heroes* link to "Heroes List")
+ * including a route parameter (passing the Hero `id` while routing to the "Hero Detail")
+ * child routes (the *Crisis Center* has its own routes)
+ * the `CanLeave` lifecycle method (ask before discarding changes)
+
+
+.l-main-section
+:marked
+ ## Milestone #1: Getting Started with the Router
+
+ Let's begin with a simple version of the app that navigates between two empty views.
+figure.image-display
+ img(src='/resources/images/devguide/router/router-1-anim.gif' alt="App in action" )
+:marked
+ ### Load the Component Router library
+ The Component Router is not part of the Angular 2 core. It is its own library.
+ The router is an optional service and you might prefer a different router someday.
+
+ The Component Router library is part of the Angular npm bundle.
+ We make it available by loading its script in our `index.html`, right after
+ the Angular core script.
++makeExample('router/ts/index.html','router-lib')(format=".")
+:marked
+ ### Set the *<base href>*
+ The Component Router uses the browser's
+ [history.pushState](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries)
+ for navigation. Thanks to `pushState`, we can make our in-app URL paths look the way we want them to
+ look, e.g. `localhost:3000/crisis-center`. Our in-app URLs can be indistinguishable from server URLs.
+
+ Modern HTML 5 browsers were the first to support `pushState` which is why many people refer to these URLs as
+ "HTML 5 style" URLs.
+
+ We must **add a [<base href> element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag**
+ to the `index.html` to make this work.
+ The `href` value specifies the base URL to use for all *relative* URLs within a document including
+ links to css files, scripts, and images.
+
+ Add the base element just after the `` tag.
+ If the `app` folder is the application root, as it is for our application,
+ set the `href` value *exactly* as shown here.
+
++makeExample('router/ts/index.html','base-href')(format=".")
+.l-sub-section
+ :marked
+ HTML 5 style navigation is the Component Router default.
+ Learn why "HTML 5" style is preferred, how to adjust its behavior, and how to switch to the
+ older hash (#) style if necessary in the [Browser URL Styles](#browser-url-styles) appendix below.
+
+:marked
+.l-sub-section
+ :marked
+ #### Live example note
+ We have to be get tricky when we run the live example because the host service sets
+ the application base address dynamically. That's why we replace the `` with a
+ script that writes a `` tag on the fly to match.
+ code-example(format="")
+ <script>document.write('<base href="' + document.location + '" />');</script>
+ :marked
+ We should only need this trick for the live example, not production code.
+:marked
+ ### Booting with the router service providers
+ Our app launches from the `boot.ts` file in the `~/app` folder so let's start there.
+ It's short and all of it is relevant to routing.
++makeExample('router/ts/app/boot.1.ts','all', 'boot.ts')(format=".")
+:marked
+ We import our root `AppComponent` and Angular's `bootstrap` function as expected.
+
+ We also import `ROUTER_PROVIDERS` from Dependency Injection.
+ The router is a service implemented by a collection of providers, most of which are identified in the
+ `ROUTER_PROVIDERS` array.
+
+ As usual, we're booting Angular with `AppComponent` as our app's root component and
+ registering providers in an array in the second parameter of the `bootstrap` function.
+ Providing the router providers at the root makes the router available everywhere in our application.
+.l-sub-section
+ :marked
+ Learn about providers, the `provide` function, and injected services in the
+ [Dependency Injection chapter](dependency-injection.html).
+:marked
+ ### The *AppComponent* shell
+ The root `AppComponent` is the shell of our application. It has title at the top, a navigation bar with two links,
+ and a "router outlet" below where the router swaps views on and off the page. Here's what we mean:
+figure.image-display
+ img(src='/resources/images/devguide/router/shell-and-outlet.png' alt="Shell" width="300" )
+:marked
+
+ The corresponding component template looks like this:
++makeExample('router/ts/app/app.component.1.ts','template')(format=".")
+:marked
+ ### *RouterOutlet*
+ `RouterOutlet` is a component from the router library.
+ The router displays views within the bounds of the `` tags.
+
+.l-sub-section
+ :marked
+ A template may hold exactly one ***unnamed*** ``.
+
+ It could have multiple ***named*** outlets (e.g., ``).
+ We'll learn about them when we get to "auxiliary routes".
+:marked
+ ### *RouterLink* binding
+ Above the outlet, within the anchor tags, we see [Property Bindings](template-syntax.html#property-binding) to
+ the `RouterLink` Directive that look like `[routerLink]="[...]"`. We imported `RouterLink` from the router library.
+
+ The template expression to the right of the equals (=) returns an *array of link parameters*.
+
+ The arrays in this example each have a single string parameter, the name of a `Route` that
+ we'll configure for this application with `@RouteConfig()`.
+
+ ### *@RouteConfig()*
+ A router holds a list of route definitions. The list is empty for a new router. We must configure it.
+
+ A router also needs a **Host Component**, a point of origin for its navigations.
+
+ It's natural to combine the creation of a new router, its configuration, and its assignment to a host component
+ in a single step. That's the purpose of the `@RouteConfig` decorator which we put to good use here:
++makeExample('router/ts/app/app.component.1.ts','route-config')(format=".")
+:marked
+ The `@RouteConfig` decorator creates a new router.
+ We applied the decorator to `AppComponent` which makes that the router's host component.
+ The argument to `@RouteConfig()` is an array of **Route Definitions**.
+
+ We're supplying two definitions:
++makeExample('router/ts/app/app.component.1.ts','route-defs')(format=".")
+:marked
+ Each definition translates to a [Route](https://angular.io/docs/ts/latest/api/router/Route-class.html) which has a
+ * `path` - the URL path segment for this route
+ * `name` - the name of the route
+ * `component` - the Component associated with this route.
+
+ The router draws upon its registry of route definition when
+ 1. the browser URL changes
+ 2. we tell the router to go to a named route
+
+ Translating these two definitions into English, we might say:
+ 1. *When the browser's location URL changes to **match the path** segment `/crisis-center`, create or retrieve an instance of
+ the `CrisisCenterComponent` and display its view.*
+
+ 1. *When the application requests navigation to a route **named** `CrisisCenter`, compose a browser URL
+ with the path segment `/crisis-center`, update the browser's address location and history, create or retrieve an instance of
+ the `CrisisCenterComponent`, and display that component's view.*
+
+ ### "Getting Started" wrap-up
+
+ We've got a very basic, navigating app, one that can switch between two views
+ when the user clicks a link.
+
+ We've learned how to
+ * load the router library
+ * add a nav bar to the shell template with anchor tags and `routerLink` directives
+ * added a `router-outlet` to the shell template where views will be displayed
+ * configure the router with `@RouterConfig`
+ * set the router to compose "HTML 5" browser URLs.
+
+ The rest of the starter app is mundane, with little interest from a router perspective.
+ Here are the details for readers inclined to build the sample through this milestone.
+
+ Our starter app's structure looks like this:
+code-example(format="").
+ router-sample
+ ├── node_modules/
+ ├── app/
+ | ├── app.component.ts
+ │ ├── boot.ts
+ │ ├── crisis-list.component.ts
+ │ └── hero-list.component.ts
+ ├── index.html
+ ├── styles.css
+ ├── tsconfig.json
+ └── package.json
+:marked
+ Here are the application-specific files
++makeTabs(
+ `router/ts/app/app.component.1.ts,
+ router/ts/app/boot.1.ts,
+ router/ts/app/hero-list.component.ts,
+ router/ts/app/crisis-list.component.ts`,
+ ',all,,',
+ `app.component.ts, boot.ts,hero-list.component.ts,crisis-list.component.ts`)
+:marked
+
+
+.l-main-section
+:marked
+ ## Milestone #2: The Heroes Feature
+
+ We've seen how to navigate using the `RouterLink` directive.
+
+ Now we'll learn some new tricks such as how to
+ * organize our app into "feature areas"
+ * navigate imperatively from one component to another
+ * pass information along in route parameters (`RouteParams`)
+
+ To demonstrate all of this we'll build out the *Heroes* feature.
+
+ ### The Heroes "feature area"
+
+ A typical application has multiple "feature areas", each an island of functionality
+ dedicated to an area of interest with its own workflow(s).
+
+ We could continue to add files to the `app/` folder.
+ That's unrealistic and ultimately not maintainable.
+ We think it's best if each feature area is in its own folder.
+
+ Our first step is to **create a separate `app/heroes/` folder**.
+ Then we'll add Hero management feature files.
+
+ We won't be creative about this. Our example is pretty much a
+ copy of the code and capabilities in the "[Tutorial: Tour of Heroes](../tutorial/index.html)".
+
+ Here's how the user will experience this version of the app
+figure.image-display
+ img(src='/resources/images/devguide/router/router-2-anim.gif' alt="App in action" )
+:marked
+ ### Add Heroes functionality
+
+ We delete the placeholder `hero-list.component.ts` that's in
+ the `app/` folder.
+
+ We create a new `hero-list.component.ts` in the `app/heroes/`
+ folder and copy over the contents of the final `heroes.component.ts` from the tutorial.
+ We also copy the `hero-detail.component.ts` and the `hero.service.ts` files
+ into the `heroes/` folder while we're at it.
+
+ When were done organizing, we have three "Hero" files:
+
+code-example(format="").
+ app/heroes/
+ ├── hero-detail.component.ts
+ ├── hero-list.component.ts
+ └── hero.service.ts
+:marked
+ Here as in the tutorial, we'll provide the `HeroService` during bootstrapping
+ so that is available anywhere in the app (see `boot.ts`) .
+
+ Now it's time for some surgery to bring these files and the rest of the app
+ into alignment with our application router.
+
+ ### New route definition with route parameter
+
+ The new Heroes feature has two interacting components, the list and the detail.
+ The list view is self-sufficient; we navigate to it, it gets a list of heroes and displays them.
+ It doesn't need any outside information.
+
+ The detail view is different. It displays a particular hero. It can't know which hero on its own.
+ That information must come from outside.
+
+ In our example, when the user selects a hero from the list, we navigate to the detail view to show that hero.
+ We'll tell the detail view which hero to display by including the selected hero's id in the route URL.
+
+ With that plan in mind, we return to the `app.component.ts` to make changes to the router's configuration
+
+ First, we import the two components from their new locations in the `app/heroes/` folder:
++makeExample('router/ts/app/app.component.2.ts','hero-import')(format=".")
+:marked
+ Then we update the `@RouteConfig` route definitions :
++makeExample('router/ts/app/app.component.2.ts','route-config')(format=".")
+:marked
+ The `CrisisCenter` and `Heroes` definitions didn't change.
+ While we moved `hero-list.component.ts` to a new location in the `app/heroes/` folder, that only affects the `import` statement;
+ it doesn't affect its route definition.
+
+ We added a new route definition for the `HeroDetailComponent` ... and this definition has a twist.
++makeExample('router/ts/app/app.component.2.ts','hero-detail-route')(format=".")
+:marked
+ Notice the `:id` token in the the path. That creates a slot in the path for a **Route Parameter**.
+ In this case, we're expecting the router to insert the `id` of a hero into that slot.
+
+ If we tell the router to navigate to the detail component and display "Magenta", we expect her `id` (15) to appear in the
+ browser URL like this:
+code-example(format="." language="bash").
+ localhost:3000/hero/15
+:marked
+ If someone enters that URL into the browser address bar, the router should recognize the
+ pattern and go to the same "Magenta" detail view.
+
+ ### Navigate to the detail imperatively
+
+ *We don't navigate to the detail component by clicking a link*.
+ We won't be adding a new anchor tag to the shell navigation bar.
+
+ Instead, we'll *detect* when the user selects a hero from the list and *command* the router
+ to present the hero detail view of the selected hero.
+
+ We'll adjust the `HeroListComponent` to implement these tasks beginning with its template:
++makeExample('router/ts/app/heroes/hero-list.component.ts','template')
+:marked
+ The template defines an `*ngFor` repeater such as [we've seen before](displaying-data.html#ngFor).
+ There's a `(click)` [EventBinding](template-syntax.html#event-binding) to the component's `select` method.
+
+ The `select` method will call the router service which we acquire by dependency injection
+ (along with the `HeroService` that gives us heroes to show):
++makeExample('router/ts/app/heroes/hero-list.component.ts','ctor')(format=".")
+:marked
+ Here's the `select` method:
++makeExample('router/ts/app/heroes/hero-list.component.ts','select')(format=".")
+:marked
+ It calls the router's **`navigate`** method with a **Link Parameters Array**.
+ This one is similar to the *link parameters array* we met [earlier](#shell-template) in an anchor tag,
+ binding to the `RouterLink` directive, only this time we're seeing it in code rather than in HTML.
+ ### Setting the route parameter
+
+ We're navigating to the `HeroDetailComponent` where we expect to see the details of the selected hero.
+ We'll need *two* pieces of information: the destination and the hero's `id`.
+
+ Accordingly, the *link parameters array* has *two* items: the **name** of the destination route and a **route parameters object** that specifies the
+ `id` of the selected hero.
++makeExample('router/ts/app/heroes/hero-list.component.ts','link-parameters-array')(format=".")
+:marked
+ The router composes the appropriate two-part destination URL:
+code-example(format="." language="bash").
+ localhost:3000/hero/15
+:marked
+ ### Getting the route parameter
+
+
+ How does the target `HeroDetailComponent` get that `id`?
+ Certainly not by analyzing the URL! That's the router's job.
+
+ The router extracts the route parameter (`id:15`) from the URL and supplies it to
+ the `HeroDetailComponent` via the **RouteParams** service.
+
+ As usual, we write a constructor that asks Angular to inject that service among the other services
+ that the component require and reference them as private variables.
++makeExample('router/ts/app/heroes/hero-detail.component.ts','ctor')(format=".")
+:marked
+ Later, in the `ngOnInit` method,
+ we ask the `RouteParams` service for the `id` parameter by name and
+ tell the `HeroService` to fetch the hero with that `id`.
++makeExample('router/ts/app/heroes/hero-detail.component.ts','ngOnInit')(format=".")
+
+.l-sub-section
+ :marked
+ Angular calls the `ngOnInit` method shortly after creating an instance of the `HeroDetailComponent`.
+
+ We put the data access logic in the `ngOnInit` method rather than inside the constructor
+ to improve the component's testability.
+ We explore this point in greater detail in the [OnInit appendix](#onInit) below.
+:marked
+ ### Navigating back to the list component
+ The `HeroDetailComponent` has a "Back" button wired to its `gotoHeroes` method that navigates imperatively
+ back to the `HeroListComponent`.
+
+ The router `navigate` method takes the same, one-item *link parameters array*, holding
+ the **name of the `HeroListComponent` route**, that we used in the `[routerLink]` directive binding.
++makeExample('router/ts/app/heroes/hero-detail.component.ts','gotoHeroes')(format=".")
+:marked
+ ### Heroes App Wrap-up
+
+ We've reached the second milestone in our router education.
+
+ We've learned how to
+ * organize our app into "feature areas"
+ * navigate imperatively from one component to another
+ * pass information along in route parameters (`RouteParams`)
+
+ After these changes, the folder structure looks like this:
+code-example(format="").
+ router-sample
+ ├── node_modules/
+ ├── app/
+ │ ├── heroes/
+ │ │ ├── hero-detail.component.ts
+ │ │ ├── hero-list.component.ts
+ │ │ └── hero.service.ts
+ │ ├── app.component.ts
+ | ├── boot.ts
+ │ └── crisis-list.component.ts
+ ├── index.html
+ ├── styles.css
+ ├── tsconfig.json
+ └── package.json
+:marked
+
+ ### The Heroes App code
+ Here are the relevant files for this version of the sample application.
++makeTabs(
+ `router/ts/app/app.component.2.ts,
+ router/ts/app/boot.2.ts,
+ router/ts/app/heroes/hero-list.component.ts,
+ router/ts/app/heroes/hero-detail.component.ts,
+ router/ts/app/heroes/hero.service.ts`,
+ `,v2,,,`,
+ `app.component.ts,
+ boot.ts,
+ hero-list.component.ts,
+ hero-detail.component.ts,
+ hero.service.ts`)
+:marked
+
+
+.l-main-section
+:marked
+ ## Milestone #3: The Crisis Center
+ The *Crisis Center* is a fake view at the moment. Time to make it useful.
+
+ The new *Crisis Center* begins as a virtual copy of the *Heroes* feature.
+ We create a new `app/crisis-center` folder, copy the Hero files,
+ and change every mention of "hero" to "crisis".
+
+ A `Crisis` has an `id` and `name`, just like a `Hero`
+ The new `CrisisListComponent` displays lists of crises.
+ When the user selects a crisis, the app navigates to the `CrisisDetailComponent`
+ for display and editing of the crisis name.
+
+ Voilà, instant feature module!
+
+ Of course this is only a sample application.
+ There's no point to this exercise unless we can learn something new.
+
+ We do have new points to make:
+
+ * The application should navigate to the *Crisis Center* by default.
+
+ * The user should be able to cancel unwanted changes.
+
+ * The router should prevent navigation away from the detail view while there are pending changes.
+
+ * When we return to the list from the detail, the previously edited crisis should be pre-selected in the list.
+ That will require passing information *back* to the list from the detail.
+
+ There are also a few lingering annoyances in the *Heroes* implementation that we can cure in the *Crisis Center*.
+
+ * We currently register every route of every view at the highest level of the application.
+ If we expand the *Crisis Center* with a 100 new views, we'll make 100 changes to the
+ `AppComponent` route configuration. If we rename a *Crisis Center* component or change a route definition,
+ we'll be changing the `AppComponent` too.
+
+ * If we followed *Heroes* lead, we'd be adding the `CrisisService` to the providers in `boot.ts`.
+ Now both `HeroService` and `CrisisService` would be available everywhere although
+ they're only needed in their respective feature modules. That stinks.
+
+ Changes to a sub-module such as *Crisis Center* shouldn't provoke changes to the `AppComponent` or `boot.ts`.
+ We need to [*separate our concerns*](https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html).
+
+ We'll fix all of these problems and add the new routing features to *Crisis Center*.
+
+ The most important fix from a router perspective will be the introduction of a **child *Routing Component***
+ with its **child router**
+
+ We'll leave *Heroes* in its less-than-perfect state to
+ serve as a contrast with what we hope is a superior *Crisis Center*.
+
+ ### A free-standing Crisis Center Feature Module
+ The *Crisis Center* is one of two application workflows.
+ Users navigate between them depending on whether they are managing crises or heroes.
+
+ The `CrisisCenter` and `Heroes` components are children of the root `AppComponent`.
+
+ Unfortunately, they and their related files are physically commingled in the same folder with the `AppComponent`.
+ We'd prefer to separate them in their own "feature areas" so they can operate and evolve independently.
+ Someday we might re-use one or the other of them in a different application.
+ Someday we might load one of them dynamically only when the user chose to enter its workflow.
+
+ Some might call it [yagni](http://martinfowler.com/bliki/Yagni.html) to even think about such things.
+ But we're right to be nervous about the way *Heroes* and *Crisis Center* artifacts are
+ bubbling up to the root `AppComponent` and blending with each other.
+ That's a [code smell](http://martinfowler.com/bliki/CodeSmell.html).
+
+ Isolating feature area modules from each other looks good to us.
+.l-sub-section
+ :marked
+ It's looking good as a general pattern for Angular applications.
+ figure.image-display
+ img(src='/resources/images/devguide/router/component-tree.png' alt="Component Tree" )
+ :marked
+ * each feature area in its own module folder
+ * each area with its own root component
+ * each area root component with its own router-outlet and child routes
+ * area routes rarely (if ever) cross
+
+:marked
+ We'll make the *Crisis Center* stand on its own and leave the *Heroes* as it is
+ so we can compare the effort, results, and consequences.
+ Then each of us can decide which path to prefer (as if we didn't already know).
+
+ ### Child Routing Component
+ We create a new `app/crisis-center` folder and add `crisis-center-component.ts` to it with the following contents:
++makeExample('router/ts/app/crisis-center/crisis-center.component.ts', 'minus-imports', 'crisis-center/crisis-center.component.ts (minus imports)')
+:marked
+ The `CrisisCenterComponent` parallels the `AppComponent`.
+
+ The `CrisisCenterComponent` is the root of the *Crisis Center* area
+ just as `AppComponent` is the root of the entire application.
+
+ This `CrisisCenterComponent` is a shell for crisis management
+ just as the `AppComponent` is a shell to manage the high-level workflow.
+
+ `AppComponent` has a `@RouteConfig` decorator that defines the top-level routes.
+ `CrisisCenterComponent` has a `@RouteConfig` decorator that defines *Crisis Center* routes.
+ The two sets of routes *do not overlap*.
+
+ `CrisisCenterComponent` template is dead simple — simpler even than the `AppComponent` template.
+ It has no content, no links, just a `` for the *Crisis Center* views.
+
+ It has no selector either. It doesn't need one. We don't *embed* this component in a parent template. We navigate to it
+ from the outside, via a parent router (more on that soon).
+
+ ### Service isolation
+ We add the `CrisisService` to the component's providers array
+ instead of registering it with the `bootstrap` function in `boot.ts`.
++makeExample('router/ts/app/crisis-center/crisis-center.component.ts', 'providers')
+:marked
+ This step limits the scope of that service to the *Crisis Center* component and its sub-component tree.
+ No component outside of the *Crisis Center* needs access to the `CrisisService`.
+ By restricting its scope, we feel confident that we can evolve it independently without fear of breaking
+ unrelated application modules — modules that *shouldn't have access to it anyway*.
+
+ ### Child Route Configuration
+ The `CrisisCenterComponent` is a *Routing Component* like the `AppComponent`.
+
+ The `@RouteConfig` decorator that adorns the `CrisisCenterComponent` class defines routes in the same way
+ that we did earlier.
++makeExample('router/ts/app/crisis-center/crisis-center.component.ts', 'route-config', 'crisis-center/crisis-center.component.ts (routes only)' )
+:marked
+ There are three *Crisis Center* routes, two of them with an `id` parameter.
+ They refer to components we haven't talked about yet but whose purpose we
+ can guess by their names.
+
+ We cannot tell just by looking at the `CrisisCenterComponent` that it is a child component
+ of an application. We can't tell that its routes are child routes.
+
+ That's entirely deliberate. The *Crisis Center* shouldn't know that it is the child of anything.
+ It might be the root of its own application. It might be repurposed in a different application.
+ The *Crisis Center* can be indifferent.
+
+ *We know* that it is child component in our application because we re-configured the
+ routes of the top-level `AppComponent` to make it so.
+:marked
+ ### Parent Route Configuration
+ Here is is the revised route configuration for the parent `AppComponent`:
++makeExample('router/ts/app/app.component.ts', 'route-config', 'app/app.component.ts (routes only)' )
+:marked
+ The second and third *Hero* routes haven't changed.
+ The first *Crisis Center* route has changed — *signficantly* — and we've formatted it to draw attention to the differences:
++makeExample('router/ts/app/app.component.ts', 'route-config-cc')(format=".")
+:marked
+ Notice that the **path ends with a slash and three trailing periods (`/...`)**.
+
+ That means this is a ***non-terminal route*** , a route that requires completion by a **child router**
+ attached to the designated component which must be a *Routing Component*.
+
+ All is well.
+ The route's component is the `CrisisCenterComponent` which we know to be a *Routing Component* with its own routes.
+
+
+
+ ### Default route (AKA *otherwise*)
+ The other big change is the addition of the `useAsDefault` property.
+ Its value is `true` which makes *this* route the *default* route.
+
+ When the `AppComponent` router sees a URL that doesn't match any of these three route paths,
+ it redirects to this 'CrisisCenter' route.
+.l-sub-section
+ :marked
+ Setting `useAsDefault = true` is the equivalent of an ***otherwise*** in other routing systems.
+:marked
+ That's how we get to the *Crisis Center* when we first launch the application.
+ At launch the URL is a host and port with no path. That doesn't match any the configured route paths.
+ So the router redirects to the *Crisis Center*.
+
+ Try any bogus address in the [live example](/resources/live-examples/router/ts/src/plnkr.html) and
+ we'll land back in the *Crisis Center*.
+ [NOT TRUE. SHOULD BE TRUE?]
+:marked
+
+:marked
+ ### PICK UP HERE
+ TODO:
+ * The RouteLink to the Crisis Center ... and how it doesn't specify the child route ... but could
+ * The route name prefixes in the route links (push that below)
+ * query parameters (no time to build an example I'm afraid)
+ * The router lifecycle hooks below
+ * decide whether to keep the # option discussion
+ * How the router interprets the link parameters array
+
+ ### Cancel and Save
+ [INTRO]
+code-example(format=".").
+ <button (click)="save()">Save</button>
+ <button (click)="cancel()">Cancel</button>
+:marked
+ [EXPLAIN]
++makeExample('router/ts/app/crisis-center/crisis-detail.component.ts', 'cancel-save', 'crisis-detail.component.ts (excerpt)')
+:marked
+ [EXPLANATION]
+
+ ### Confirm before leaving with unsaved changes
+ [INTRO]
++makeExample('router/ts/app/crisis-center/crisis-detail.component.ts', 'canDeactivate', 'crisis-detail.component.ts (excerpt)')
+:marked
+ [EXPLANATION]
+ ### Re-select crisis in the list via route param
+ [INTRO]
++makeExample('router/ts/app/crisis-center/crisis-detail.component.ts', 'gotoCrises', 'crisis-detail.component.ts (excerpt)')
+:marked
+ [EXPLANATION]
++makeExample('router/ts/app/crisis-center/crisis-list.component.ts', 'isSelected', 'crisis-list.component.ts (excerpt)')
+:marked
+ [EXPLANATION]
+code-example(format=".").
+ [class.selected]="isSelected(crisis)"
+:marked
+
+
+
+.l-main-section
+:marked
+ ## The Finished App
+ As we end our chapter together, we take a parting look at
+ the entire application.
+
+ ### Folder structure
+ Our final project folder structure looks like this:
+code-example(format="").
+ router-sample
+ ├── node_modules/
+ ├── src/
+ ├── app/
+ │ ├── crisis-center/...
+ │ ├── heroes/...
+ │ ├── app.component.ts
+ │ ├── boot.ts
+ │ └── dialog.service.ts
+ ├── index.html
+ ├── styles.css
+ ├── tsconfig.json
+ └── package.json
+:marked
+ The top level application files are
++makeTabs(
+ `router/ts/app/app.component.ts,
+ router/ts/app/boot.ts,
+ router/ts/app/dialog.service.ts,
+ router/ts/index.html,
+ router/ts/styles.css
+ `,
+ null,
+ `app.component.ts,
+ boot.ts,
+ dialog.service.ts,
+ index.html,
+ styles.css
+ `)
+:marked
+
+ ### Crisis Center
+ The *Crisis Center* feature area within the `crisis-center` folder follows:
+code-example(format="").
+ app/
+ crisis-center/
+ ├── crisis-center.component.ts
+ ├── crisis-detail.component.ts
+ ├── crisis-list.component.ts
+ ├── crisis.service.ts
+ └── routes.ts
+:marked
++makeTabs(
+ `router/ts/app/crisis-center/crisis-center.component.ts,
+ router/ts/app/crisis-center/crisis-list.component.ts,
+ router/ts/app/crisis-center/crisis-detail.component.ts,
+ router/ts/app/crisis-center/crisis.service.ts
+ `,
+ null,
+ `crisis-center.component.ts,
+ crisis-list.component.ts,
+ crisis-detail.component.ts,
+ crisis.service.ts,
+ `)
+:marked
+ ### Heroes
+ The *Heroes* feature area within the `heroes` folder is next:
+code-example(format="").
+ app/
+ heroes/
+ ├── hero-detail.component.ts
+ ├── hero-list.component.ts
+ └── hero.service.ts
+:marked
++makeTabs(
+ `router/ts/app/heroes/hero-list.component.ts,
+ router/ts/app/heroes/hero-detail.component.ts,
+ router/ts/app/heroes/hero.service.ts
+ `,
+ null,
+ `hero-list.component.ts,
+ hero-detail.component.ts,
+ hero.service.ts
+ `)
+:marked
+
+
+.l-main-section
+:marked
+ ## Appendix: Why use an *ngOnInit* method
+
+ We implemented an `ngOnInit` method in many of our Component classes.
+ We did so, for example, in the [HeroDetailComponent](#hero-detail-ctor).
+ We might have put the `ngOnInit` logic inside the constructor instead. We didn't for a reason. The reason is *testability*.
+
+ A constructor that has major side-effects can be difficult to test because it starts doing things as soon as
+ we create a test instance. In this case, it might have made a request to a remote server, something it shouldn't
+ do under test. It may even be impossible to reach the server in the test environment.
+
+ The better practice is to limit what the constructor can do. Mostly it should stash parameters in
+ local variables and perform simple instance configuration.
+
+ Yet we want an instance of this class to get the hero data from the `HeroService` soon after it is created.
+ How do we ensure that happens if not in the constructor?
+
+ Angular detects when a component has certain lifecycle methods like
+ [ngOnInit](https://angular.io/docs/ts/latest/api/core/OnInit-interface.html) and
+ [ngOnDestroy](https://angular.io/docs/ts/latest/api/core/OnDestroy-interface.html) and calls them
+ at the appropriate moment.
+
+ Angular will call `ngOnInit` when we navigate to the `HeroDetailComponent`, we'll get the `id` from the `RouteParams`
+ and ask the server for the hero with that `id`.
+
+ We too can call that `ngOnInit` method in our tests if we wish ... after taking control of the injected
+ `HeroService` and (perhaps) mocking it.
+
+
+.l-main-section
+:marked
+ ## Appendix: Browser URL styles
+
+ When the router navigates to a new component view, it updates the browser's location and history
+ with a URL for that view.
+ This is a strictly local URL. The browser shouldn't send a request to the server
+ and should not reload the page.
+.l-sub-section
+ :marked
+ We're talking now about the ***browser*** URL
+ **not** the *route* URL that we record in a `RouteDefinition`.
+ The browser URL is what we paste into the browser's **address bar**
+ and email to folks so they can deep-link into an application page.
+:marked
+ Modern HTML 5 browsers support
+ [history.pushState](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries),
+ a technique that changes a browser's location and history without triggering a server page request.
+ The router can compose a "natural" URL that is indistinguishable from
+ one that would otherwise require a page load.
+
+ Here's the *Crisis Center* URL in this "HTML 5 pushState" style:
+code-example(format=".", language="bash").
+ localhost:3002/crisis-center/
+:marked
+ Older browsers send page requests to the server when the location URL changes ...
+ unless the change occurs after a "#" (called the "hash").
+ Routers take advantage of this exception by composing in-application route
+ URLs with hashes. Here's a "hash URL" that routes to the *Crisis Center*
+code-example(format=".", language="bash").
+ localhost:3002/src/#/crisis-center/
+:marked
+ The Angular Component Router supports both styles.
+ We set our preference by providing a `LocationStrategy` during the bootstrapping process.
+.l-sub-section
+ :marked
+ Learn about "providers" and the bootstrap process in the
+ [Dependency Injection chapter](dependency-injection#bootstrap)
+:marked
+ ### Which Strategy is Best?
+ We must choose a strategy and we need to make the right call early in the project.
+ It won't be easy to change later once the application is in production
+ and there are lots of application URL references in the wild.
+
+ Almost all Angular 2 projects should use the default HTML 5 style.
+ It produces URLs that are easier for users to understand.
+ And it preserves the option to do **server-side rendering** later.
+
+ Rendering critical pages on the server is a technique that can greatly improve
+ perceived responsiveness when the app first loads.
+ An app that would otherwise take ten or more seconds to start
+ could be rendered on the server and delivered to the user's device
+ in less than a second.
+
+ Thist option is only available if application URLs look like normal web URLs
+ without hashes (#) in the middle.
+
+ Stick with the default unless you have a compelling reason to
+ resort to hash routes.
+
+ ### HTML 5 URLs and the *<base href>*
+ The router use the "[HTML 5 pushState](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries)"
+ style by default.
+ We don't have to provide the router's `PathLocationStrategy` because it's loaded automatically.
+
+ We *must* add a
+ [<base href> element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag
+ in the `` of the `index.html`.
++makeExample('router/ts/index.html','base-href')(format=".")
+:marked
+ Without that tag, the browser may not be be able to load resources
+ (images, css, scripts) when "deep linking" into the app.
+ Bad things could happen when someone pastes an application link into the
+ browser's address bar or clicks such a link in an email link.
+
+ Some developers may not be able to add the `` element, perhaps because they don't have
+ access to `` or the `index.html`.
+
+ Those developers may still use HTML 5 URLs by taking two remedial steps:
+
+ 1. Provide the router with an appropriate `APP_BASE_HREF` value.
+ 1. Use **absolute URLs** for all web resources: css, images, scripts, and template html files.
+
+.l-sub-section
+ :marked
+ Learn about the [APP_BASE_HREF](https://angular.io/docs/ts/latest/api/router/APP_BASE_HREF-const.html)
+ in the API Guide.
+:marked
+ ### *HashLocationStrategy*
+ We can go old-school with the `HashLocationStrategy` by
+ providing it as the router's `LocationStrategy` during application bootstrapping.
+
+ That means importing `provide` for Dependency Injection and the
+ `Location` and `HashLocationStrategy` symbols from the router,
+ then providing that strategy in the call to `bootstrap`:
++makeExample('router/ts/app/boot.2.ts', 'hash-strategy')
diff --git a/public/docs/ts/latest/guide/template-syntax.jade b/public/docs/ts/latest/guide/template-syntax.jade
index b1cc811543..a7043de079 100644
--- a/public/docs/ts/latest/guide/template-syntax.jade
+++ b/public/docs/ts/latest/guide/template-syntax.jade
@@ -784,15 +784,15 @@ figure.image-display
Here’s an example:
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch')(format=".")
:marked
- We bind the parent `NgSwitch` element to an expression returning a “switch value”. The value is a string in this example but it can be a value of any type.
+ We bind the parent `NgSwitch` directive to an expression returning a “switch value”. The value is a string in this example but it can be a value of any type.
- The parent `NgSwitch` element controls a set of child`` elements. Each `` wraps a candidate subtree. A template is either pegged to a “match value” expression or marked as the default template.
+ The parent `NgSwitch` directive controls a set of child`` elements. Each `` wraps a candidate subtree. A template is either pegged to a “match value” expression or marked as the default template.
**At any particular moment, only one of these templates will be rendered**
If the template’s “match value” equals the “switch value”, Angular adds the template’s sub-tree to the DOM. If no template is a match and there is a default template, Angular adds the default template’s sub-tree to the DOM. Angular removes and destroys the sub-tree’s of all other templates.
- There are three related directives at work here.
+ There are three collaborating directives at work here.
1. `ngSwitch` - bound to an expression that returns the switch value.
1. `ngSwitchWhen` - bound to an expression returning a match value.
1. `ngSwitchDefault` - a marker attribute on the default template.
diff --git a/public/resources/images/devguide/router/complete-nav.png b/public/resources/images/devguide/router/complete-nav.png
new file mode 100644
index 0000000000..1dca8a7fe7
Binary files /dev/null and b/public/resources/images/devguide/router/complete-nav.png differ
diff --git a/public/resources/images/devguide/router/component-tree.png b/public/resources/images/devguide/router/component-tree.png
new file mode 100644
index 0000000000..92a1a74326
Binary files /dev/null and b/public/resources/images/devguide/router/component-tree.png differ
diff --git a/public/resources/images/devguide/router/confirm-dialog.png b/public/resources/images/devguide/router/confirm-dialog.png
new file mode 100644
index 0000000000..a152d301b5
Binary files /dev/null and b/public/resources/images/devguide/router/confirm-dialog.png differ
diff --git a/public/resources/images/devguide/router/crisis-center-detail.png b/public/resources/images/devguide/router/crisis-center-detail.png
new file mode 100644
index 0000000000..1c1275c2f7
Binary files /dev/null and b/public/resources/images/devguide/router/crisis-center-detail.png differ
diff --git a/public/resources/images/devguide/router/crisis-center-list.png b/public/resources/images/devguide/router/crisis-center-list.png
new file mode 100644
index 0000000000..5c91b597dc
Binary files /dev/null and b/public/resources/images/devguide/router/crisis-center-list.png differ
diff --git a/public/resources/images/devguide/router/hero-detail.png b/public/resources/images/devguide/router/hero-detail.png
new file mode 100644
index 0000000000..a5d9335763
Binary files /dev/null and b/public/resources/images/devguide/router/hero-detail.png differ
diff --git a/public/resources/images/devguide/router/hero-list.png b/public/resources/images/devguide/router/hero-list.png
new file mode 100644
index 0000000000..9c902ba774
Binary files /dev/null and b/public/resources/images/devguide/router/hero-list.png differ
diff --git a/public/resources/images/devguide/router/router-1-anim.gif b/public/resources/images/devguide/router/router-1-anim.gif
new file mode 100644
index 0000000000..f5992a65e1
Binary files /dev/null and b/public/resources/images/devguide/router/router-1-anim.gif differ
diff --git a/public/resources/images/devguide/router/router-2-anim.gif b/public/resources/images/devguide/router/router-2-anim.gif
new file mode 100644
index 0000000000..86a6bb266e
Binary files /dev/null and b/public/resources/images/devguide/router/router-2-anim.gif differ
diff --git a/public/resources/images/devguide/router/router-anim.gif b/public/resources/images/devguide/router/router-anim.gif
new file mode 100644
index 0000000000..319ffe0bf1
Binary files /dev/null and b/public/resources/images/devguide/router/router-anim.gif differ
diff --git a/public/resources/images/devguide/router/shell-and-outlet.png b/public/resources/images/devguide/router/shell-and-outlet.png
new file mode 100644
index 0000000000..c9e8da0b32
Binary files /dev/null and b/public/resources/images/devguide/router/shell-and-outlet.png differ