+
+```
+
+Now let's look at the test.
+
+```javascript
+describe('ConversationsCmp', () => {
+ let params: BehaviorSubject;
+ let data: BehaviorSubject;
+
+ beforeEach(async(() => {
+ params = of({
+ folder: 'inbox'
+ });
+
+ data = of({
+ conversations: [
+ {
+ id: 1,
+ title: 'On the Genealogy of Morals by Nietzsche',
+ user: {name: 'Kate', email: 'katez@example.com'}
+ },
+ {
+ id: 2,
+ title: 'Ethics by Spinoza',
+ user: {name: 'Corin', email: 'corin@example.com'}
+ }
+ ]
+ });
+
+ TestBed.configureTestingModule({
+ declarations: [ConversationsCmp],
+ providers: [
+ { provide: ActivatedRoute, useValue: {params, data} }
+ ]
+ });
+ TestBed.compileComponents();
+ }));
+
+ it('updates the list of conversations', () => {
+ const f = TestBed.createComponent(ConversationsCmp);
+ f.detectChanges();
+
+ expect(f.debugElement.nativeElement).toHaveText('inbox');
+ expect(f.debugElement.nativeElement).toHaveText('On the Genealogy of Morals');
+ expect(f.debugElement.nativeElement).toHaveText('Ethics');
+
+ params.next({
+ folder: 'drafts'
+ });
+
+ data.next({
+ conversations: [
+ { id: 3, title: 'Fear and Trembling by Kierkegaard', user: {name: 'Someone Else', email: 'someonelse@example.com'} }
+ ]
+ });
+ f.detectChanges();
+
+ expect(f.debugElement.nativeElement).toHaveText('drafts');
+ expect(f.debugElement.nativeElement).toHaveText('Fear and Trembling');
+ });
+});
+```
+
+First, look at how we configured our testing module. We only declared `ConversationsCmp`, nothing else. This means that all the elements in the template will be treated as simple DOM nodes, and only common directives (e.g., ngIf and ngFor) will be applied. This is exactly what we want. Second, instead of using a real activated route, we are using a fake one, which is just an object with the params and data properties.
+
+## Integration Testing
+
+Finally, we can always write an integration test that will exercise the whole application.
+
+```javascript
+describe('integration specs', () => {
+ const initialData = {
+ conversations: [
+ {id: 1, title: 'The Myth of Sisyphus'},
+ {id: 2, title: 'The Nicomachean Ethics'}
+ ],
+ messages: [
+ {id: 1, conversationId: 1, text: 'The Path of the Absurd Man'}
+ ]
+ };
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ // MailModule is an NgModule that contains all application
+ // components and the router configuration
+
+ // RouterTestingModule overrides the router and location providers
+ // to make them test-friendly.
+ imports: [MailModule, RouterTestingModule],
+
+ providers: [
+ { provide: 'initialData', useValue: initialData}
+ ]
+ });
+ TestBed.compileComponents();
+ }));
+
+ it('should navigate to a conversation', fakeAsync(() => {
+ // get the router from the testing NgModule
+ const router = TestBed.get(Router);
+
+ // get the location from the testing NgModule,
+ // which is a SpyLocation that comes from RouterTestingModule
+ const location = TestBed.get(Location);
+
+ // compile the root component of the app
+ const f = TestBed.createComponent(MailAppCmp);
+
+ router.navigateByUrl("/inbox");
+ advance(f);
+
+ expect(f.debugElement.nativeElement).toHaveText('The Myth of Sisyphus');
+ expect(f.debugElement.nativeElement).toHaveText('The Nicomachean Ethics');
+
+ // find the link
+ const c = f.debugElement.query(e => e.nativeElement.textContent === "The Myth of Sisyphus");
+ c.nativeElement.click();
+ advance(f);
+
+ expect(location.path()).toEqual("/inbox/0");
+ expect(f.nativeElement).toHaveText('The Path of the Absurd Man');
+ }));
+});
+
+function advance(f: ComponentFixture) {
+ tick();
+ f.detectChanges();
+}
+```
+
+Even though both the shallow and integration tests render components, these tests are very different in nature. In the shallow test we mocked up every single dependency of a component. In the integration one we did it only with the location service. Shallow tests are isolated, and, as a result, can be used to drive the design of our components. Integration tests are only used to check the correctness.
+
+
+## Summary
+
+In this chapter we looked at three ways to test Angular components: isolated tests, shallow tests, and integration tests. Each of them have their time and place: isolated tests are a great way to test drive your components and test complex logic. Shallow tests are isolated tests on steroids, and they should be used when writing a meaningful test requires to render a component's template. Finally, integration tests verify that a group of components and services (e.g., the router) work together.
diff --git a/14_config.md b/14_config.md
new file mode 100644
index 0000000..392d6ff
--- /dev/null
+++ b/14_config.md
@@ -0,0 +1,156 @@
+# Chapter 12: Configuration
+
+In this last chapter we will look at configuring the router.
+
+## Importing RouterModule
+
+We configure the router by importing `RouterModule`, and there are two ways to do it: `RouterModule.forRoot` and `RouterModule.forChild`.
+
+`RouterModule.forRoot` creates a module that contains all the router directives, the given routes, and the router service itself. And `RouterModule.forChild` creates a module that contains all the directives and the given routes, but does not include the service.
+
+The router library provides two ways to configure the module because it deals with a shared mutable resource--location. That is why we cannot have more than one router service active--they would clobber each other. Therefore we can use `forChild` to configure every lazy-loaded child module, and `forRoot` at the root of the application. `forChild` can be called multiple times, whereas `forRoot` can be called only once.
+
+```javascript
+@NgModule({
+ imports: [RouterModule.forRoot(ROUTES)]
+})
+class MailModule {}
+
+@NgModule({
+ imports: [RouterModule.forChild(ROUTES)]
+})
+class ContactsModule {}
+```
+
+## Configuring Router Service
+
+We can configure the router service by passing the following options to `RouterModule.forRoot`:
+
+* `enableTracing` makes the router log all its internal events to the console.
+* `useHash` enables the location strategy that uses the URL fragment instead of the history API.
+* `initialNavigation` disables the initial navigation.
+* `errorHandler` provides a custom error handler.
+
+Let's look at each of them in detail.
+
+### Enable Tracing
+
+Setting `enableTracing` to true is a great way to learn how the router works.
+
+```javascript
+@NgModule({
+ imports: [RouterModule.forRoot(ROUTES, {enableTracing: true})]
+})
+class MailModule {}
+```
+
+With this option set, the router will log every internal event to the your console. You'll see something like this:
+
+```
+Router Event: NavigationStart
+NavigationStart(id: 1, url: '/inbox')
+
+Router Event: RoutesRecognized
+RoutesRecognized(id: 1, url: '/inbox', urlAfterRedirects: '/inbox', state:
+ Route(url:'', path:'') {
+ Route(url:'inbox', path:':folder') {
+ Route(url:'', path:'')
+ }
+ }
+)
+
+Router Event: NavigationEnd
+NavigationEnd(id: 1, url: '/inbox', urlAfterRedirects: '/inbox')
+
+
+Router Event: NavigationStart
+NavigationStart(id: 2, url: '/inbox/0')
+
+Router Event: RoutesRecognized
+RoutesRecognized(id: 2, url: '/inbox/0', urlAfterRedirects: '/inbox/0', state:
+ Route(url:'', path:'') {
+ Route(url:'inbox', path:':folder') {
+ Route(url:'0', path:':id') {
+ Route(url:'', path:'')
+ }
+ }
+ }
+)
+
+Router Event: NavigationEnd
+NavigationEnd(id: 2, url: '/inbox/0', urlAfterRedirects: '/inbox/0')
+```
+
+You can right click on any of the events and store them as global variables. This allows you to interact with them: inspect router state snapshots, URLs, etc..
+
+### Use Hash
+
+The router supports two location strategies out of the box: the first one uses the browser history API, and the second one uses the URL fragment or hash. To enable the hash strategy, do the following:
+
+```javascript
+@NgModule({
+ imports: [RouterModule.forRoot(ROUTES, {useHash: true})]
+})
+class MailModule {}
+```
+
+You can also provide your own custom strategy as follows:
+
+```javascript
+@NgModule({
+ imports: [RouterModule.forRoot(ROUTES)],
+ providers: [{provide: LocationStrategy, useClass: MyCustomLocationStrategy}]
+})
+class MailModule {}
+```
+
+## Disable Initial Navigation
+
+By default, `RouterModule.forRoot` will trigger the initial navigation: the router will read the current URL and will navigate to it. We can disable this behavior to have more control.
+
+```javascript
+@NgModule({
+ imports: [RouterModule.forRoot(ROUTES, {initialNavigation: false})],
+})
+class MailModule {
+ constructor(router: Router) {
+ router.navigateByUrl("/fixedUrl");
+ }
+}
+```
+
+## Custom Error Handler
+
+Every navigation will either succeed, will be canceled, or will error. There are two ways to observe this.
+
+The `router.events` observable will emit:
+
+* `NavigationStart` when navigation stars.
+* `NavigationEnd` when navigation succeeds.
+* `NavigationCancel` when navigation is canceled.
+* `NavigationError` when navigation fails.
+
+All of them contain the `id` property we can use to group the events associated with a particular navigation.
+
+If we call `router.navigate` or `router.navigateByUrl` directly, we will get a promise that:
+
+* will be resolved with `true` if the navigation succeeds.
+* will be resolved with `false` if the navigation gets canceled.
+* will be rejected if the navigation fails.
+
+Navigation fails when the router cannot match the URL or an exception is thrown during the navigation. Usually this indicates a bug in the application, so failing is the right strategy, but not always. We can provide a custom error handler to recover from certain errors.
+
+```javascript
+function treatCertainErrorsAsCancelations(error) {
+ if (error isntanceof CancelException) {
+ return false; //cancelation
+ } else {
+ throw error;
+ }
+}
+
+@NgModule({
+ imports: [RouterModule.forRoot(ROUTES, {errorHandler: treatCertainErrorsAsCancelations})]
+})
+class MailModule {}
+```
diff --git a/15_last.md b/15_last.md
new file mode 100644
index 0000000..c766305
--- /dev/null
+++ b/15_last.md
@@ -0,0 +1,11 @@
+# Fin
+
+This is the end of this short book on the Angular Router. We have learned a lot. We looked at what routers do in general: they are responsible for manage state transitions. Then we looked at the Angular2 router: its mental model, its API, and the design principles behind it. We also learned how to test applications using the router, and how to configure it.
+
+## Bug Reports
+
+If you find any typos, or have suggestions on how to improve the book, please, email me at avix1000@gmail.com.
+
+### Example App
+
+Throughout the book I used the same application in all the examples. You can find the source code of this application here: [MailApp](https://github.com/vsavkin/router_mailapp).
diff --git a/2_example.md b/2_example.md
new file mode 100644
index 0000000..830e893
--- /dev/null
+++ b/2_example.md
@@ -0,0 +1,5 @@
+# Example
+
+For all the examples in this book we will use MailApp, which is an application akin to Inbox or Gmail. At launch, the application displays a list of conversations, which we can browse through. Once we click on a conversation, we can see all its messages. We can also compose a new message, or view an existing message in a popup.
+
+You can find the source code of the MailApp application here: [MailApp](https://github.com/vsavkin/router_mailapp).
\ No newline at end of file
diff --git a/3_routing_is_all_about.md b/3_routing_is_all_about.md
new file mode 100644
index 0000000..2959380
--- /dev/null
+++ b/3_routing_is_all_about.md
@@ -0,0 +1,81 @@
+# Chapter 1: What Do Routers Do?
+
+Before we jump into the specifics of the Angular router, let's talk about what routers do in general.
+
+As you know, an Angular application is a tree of components. Some of these components are reusable UI components (e.g., list, table), and some are application components, which represent screens or some logical parts of the application. The router cares about application components, or, to be more specific, about their arrangements. Let's call such component arrangements router states. So a router state defines what is visible on the screen.
+
+
+I> A router state is an arrangement of application components that defines what is visible on the screen.
+
+### Router Configuration
+
+The router configuration defines all the potential router states of the application. Let's look at an example.
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ ]
+ },
+ {
+ path: 'compose',
+ component: ComposeCmp,
+ outlet: 'popup'
+ },
+ {
+ path: 'message/:id',
+ component: PopupMessageCmp,
+ outlet: 'popup'
+ }
+]
+```
+
+Don't worry about understanding all the details. I will cover them in later chapters. For now, let's depict the configuration as follows:
+
+{width=80%}
+
+
+As you can see the router configuration is a tree, with every node representing a route. Some nodes have components associated with them, some do not. We also use color to designate different outlets, where an outlet is a location in the component tree where a component is placed.
+
+### Router State
+
+A router state is a subtree of the configuration tree. For instance, the example below has `ConversationsCmp` activated. We say *activated* instead of *instantiated* as a component can be instantiated only once but activated multiple times (any time its route's parameters change).
+
+{width=80%}
+
+
+Not all subtrees of the configuration tree are valid router states. If a node has multiple children of the same color, i.e., of the same outlet name, only one of them can be active at a time. For instance, `ComposeCmp` and `PopupMessageCmp` cannot be displayed together, but `ConversationsCmp` and `PopupMessageCmp` can. Stands to reason, an outlet is nothing but a location in the DOM where a component is placed. So we cannot place more than one component into the same location at the same time.
+
+### Navigation
+
+The router's primary job is to manage navigation between states, which includes updating the component tree.
+
+I> Navigation is the act of transitioning from one router state to another.
+
+To see how it works, let's look at the following example. Say we perform a navigation from the state above to this one:
+
+{width=80%}
+
+
+Because `ConversationsCmp` is no longer active, the router will remove it. Then, it will instantiate `ConversationCmp` with `MessagesCmp` in it, with `ComposeCmp` displayed as a popup.
+
+### Summary
+
+That's it. The router simply allows us to express all the potential states which our application can be in, and provides a mechanism for navigating from one state to another. The devil, of course, is in the implementation details, but understanding this mental model is crucial for understanding the implementation.
+
+### Isn't it all about the URL?
+
+The URL bar provides a huge advantage for web applications over native ones. It allows us to reference states, bookmark them, and share them with our friends. In a well-behaved web application, any application state transition results in a URL change, and any URL change results in a state transition. In other words, a URL is nothing but a serialized router state. The Angular router takes care of managing the URL to make sure that it is always in-sync with the router state.
\ No newline at end of file
diff --git a/4_angular_router_overview.md b/4_angular_router_overview.md
new file mode 100644
index 0000000..d2fbee1
--- /dev/null
+++ b/4_angular_router_overview.md
@@ -0,0 +1,327 @@
+# Chapter 2: Overview
+
+Now that we have learned what routers do in general, it is time to talk about the Angular router.
+
+
+
+The Angular router takes a URL, then:
+
+1. Applies redirects
+2. Recognizes router states
+3. Runs guards and resolves data,
+4. Activates all the needed components
+5. Manages navigation
+
+Most of it happens behind the scenes, and, usually, we do not need to worry about it. But remember, the purpose of this book is to teach you how to configure the router to handle any crazy requirement your application might have. So let's get on it!
+
+### URL Format
+
+Since I will use a lot of URLs in the examples below, let's quickly look at the URL format.
+
+ /inbox/33(popup:compose)
+
+ /inbox/33;open=true/messages/44
+
+As you can see, the router uses parentheses to serialize secondary segments (e.g., popup:compose), the colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to specify route specific parameters.
+
+---
+
+In the examples below we assume that we have given the following configuration to the router, and we are navigating to `'/inbox/33/messages/44'`.
+
+```javascript
+[
+ { path: '', pathMatch: 'full', redirectTo: '/inbox' },
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ ]
+ },
+ {
+ path: 'compose',
+ component: ComposeCmp,
+ outlet: 'popup'
+ },
+ {
+ path: 'message/:id',
+ component: PopupMessageCmp,
+ outlet: 'popup'
+ }
+]
+```
+
+## Applying Redirects
+
+
+
+The router gets a URL from the user, either when she clicks on a link or updates the location bar directly. The first thing that router does with this URL is it will apply any redirects.
+
+What is a redirect?
+
+I> A redirect is a substitution of a URL segment. Redirects can either be local or absolute. Local redirects replace a single segment with a different one. Absolute redirects replace the whole URL. Redirects are local unless you prefix the url with a slash.
+
+The provided configuration has only one redirect rule: `{ path: '', pathMatch: 'full', redirectTo: '/inbox' }`, i.e., replace `'/'` with `'/inbox'`. This redirect is absolute because the redirectTo value starts with a slash.
+
+Since we are navigating to `'/inbox/33/messages/44'` and not `'/'`, the router will not apply any redirects, and the URL will stay as is.
+
+
+## Recognizing States
+
+
+
+Next, the router will derive a router state from the URL. To understand how this phase works, we need to learn a bit about how the router matches the URL.
+
+The router goes through the array of routes, one by one, checking if the URL starts with a route's path. Here it will check that `'/inbox/33/messages/44'` starts with ':folder'. It does, since ‘:folder’ is what is called a ‘variable segment’. It is a parameter where normally you’d expect to find a constant string. Since it is a variable, virtually any string will match it. In our case ‘inbox’ will match it. So the router will set the folder parameter to 'inbox', then it will take the children configuration items, the rest of the URL `'33/messages/44'`, and will carry on matching. As a result, the id parameter will be set to '33', and, finally, the `'messages/:id'` route will be matched with the second id parameter set to '44'.
+
+If the taken path through the configuration does not "consume" the whole URL, the router backtracks to try an alternative path. If it is impossible to match the whole URL, the navigation fails. But if it works, the router state representing the future state of the application will be constructed.
+
+{width=80%}
+
+
+A router state consists of activated routes. And each activated route can be associated with a component. Also, note that we always have an activated route associated with the root component of the application.
+
+
+## Running Guards
+
+
+
+At this stage we have a future router state. Next, the router will check that transitioning to the new state is permitted. It will do this by running guards. We will cover guards in detail in next chapters. For now, it is sufficient to say that a guard is a function that the router runs to make sure that a navigation to a certain URL is permitted.
+
+
+## Resolving Data
+
+After the router has run the guards, it will resolve the data. To see how it works, let's tweak our configuration from above.
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp,
+ resolve: {
+ conversations: ConversationsResolver
+ }
+ }
+ ]
+ }
+]
+```
+
+Where `ConversationsResolver` is defined as follows:
+
+```javascript
+@Injectable()
+class ConversationsResolver implements Resolve {
+ constructor(private repo: ConversationsRepo, private currentUser: User) {}
+
+ resolve(route: ActivatedRouteSnapshot, state: RouteStateSnapshot):
+ Promise {
+ return this.repo.fetchAll(route.params['folder'], this.currentUser);
+ }
+}
+```
+
+Finally, we need to register `ConversationsResolver` when bootstrapping our application.
+
+```javascript
+@NgModule({
+ //...
+ providers: [ConversationsResolver],
+ bootstrap: [MailAppCmp]
+})
+class MailModule {
+}
+
+platformBrowserDynamic().bootstrapModule(MailModule);
+```
+
+Now when navigating to `'/inbox'`, the router will create a router state, with an activated route for the conversations component. That route will have the folder parameter set to 'inbox'. Using this parameter with the current user, we can fetch all the inbox conversations for that user.
+
+We can access the resolved data by injecting the activated route object into the conversations component.
+
+```javascript
+@Component({
+ template: `
+
+ `
+})
+class ConversationsCmp {
+ conversations: Observable;
+ constructor(route: ActivatedRoute) {
+ this.conversations = route.data.pluck('conversations');
+ }
+}
+```
+
+## Activating Components
+
+
+
+At this point, we have a router state. The router can now activate this state by instantiating all the needed components, and placing them into appropriate router outlets.
+
+To understand how it works, let's take a look at how we use router outlets in a component template.
+
+The root component of the application has two outlets: primary and popup.
+
+```javascript
+@Component({
+ template: `
+ ...
+
+
+ ...
+
+ `
+})
+class MailAppCmp {
+}
+```
+
+Other components, such as `ConversationCmp`, have only one.
+
+```javascript
+@Component({
+ template: `
+ ...
+
+ ...
+ `
+})
+class ConversationCmp {
+}
+```
+
+
+Now imagine we are navigating to `'/inbox/33/messages/44(popup:compose)'`.
+
+That's what the router will do. First, it will instantiate `ConversationCmp` and place it into the primary outlet of the root component. Then, it will place a new instance of `ComposeCmp` into the 'popup' outlet. Finally, it will instantiate a new instance of `MessageCmp` and place it in the primary outlet of the just created conversation component.
+
+
+### Using Parameters
+
+Often components rely on parameters or resolved data. For instance, the conversation component probably need to access the conversation object. We can get the parameters and the data by injecting `ActivatedRoute`.
+
+```javascript
+@Component({...})
+class ConversationCmp {
+ conversation: Observable;
+ id: Observable;
+
+ constructor(r: ActivatedRoute) {
+ // r.data is an observable
+ this.conversation = r.data.map(d => d.conversation);
+
+ // r.params is an observable
+ this.id = r.params.map(p => p.id);
+ }
+}
+```
+
+If we navigate from `'/inbox/33/messages/44(popup:compose)'` to
+
+`'/inbox/34/messages/45(popup:compose)'`, the data observable will emit a new 'map' with the new object, and the conversation component will display the information about Conversation 34.
+
+As you can see the router exposes parameters and data as observables, which is convenient most of the time, but not always. Sometimes what we want is a snapshot of the state that we can examine at once.
+
+```javascript
+@Component({...})
+class ConversationCmp {
+ conversation: Conversation;
+ constructor(r: ActivatedRoute) {
+ const s: ActivatedRouteSnapshot = r.snapshot;
+ this.conversation = s.data['conversation']; // Conversation
+ }
+}
+```
+
+
+## Navigation
+
+
+
+So at this point the router has created a router state and instantiated the components. Next, we need to be able to navigate from this router state to another one. There are two ways to accomplish this: imperatively, by calling `router.navigate`, or declaratively, by using the `RouterLink` directive.
+
+### Imperative Navigation
+
+To navigate imperatively, inject the `Router` service and call navigate.
+
+```javascript
+@Component({...})
+class MessageCmp {
+ public id: string;
+ constructor(private route: ActivatedRoute, private router: Router) {
+ route.params.subscribe(_ => this.id = _.id);
+ }
+
+ openPopup(e) {
+ this.router.navigate([{outlets: {popup: ['message', this.id]}}]).then(_ => {
+ // navigation is done
+ });
+ }
+}
+```
+
+### RouterLink
+
+Another way to navigate around is by using the `RouterLink` directive.
+
+```javascript
+@Component({
+ template: `
+ Edit
+ `
+})
+class MessageCmp {
+ public id: string;
+ constructor(private route: ActivatedRoute) {
+ route.params.subscribe(_ => this.id = _.id);
+ }
+}
+```
+
+This directive will also update the href attribute when applied to an `` link element, so it is SEO friendly and the right-click open-in-new-browser-tab behavior we expect from regular links will work.
+
+## Summary
+
+Let's look at all the operations of the Angular router one more time.
+
+
+
+When the browser is loading `'/inbox/33/messages/44(popup:compose)'`, the router will do the following. First, it will apply redirects. In this example, none of them will be applied, and the URL will stay as is. Then the router will use this URL to construct a new router state.
+
+{width=80%}
+
+
+Next, the router will instantiate the conversation and message components.
+
+{width=80%}
+
+
+Now, let's say the message component has the following link in its template:
+
+```html
+Edit
+```
+
+The router link directive will take the array and will set the href attribute to
+
+ `'/inbox/33/messages/44(popup:message/44)'`.
+
+Now, the user triggers a navigation by clicking on the link. The router will take the constructed URL and start the process all over again: it will find that the conversation and message components are already in place. So no work is needed there. But it will create an instance of `PopupMessageCmp` and place it into the popup outlet. Once this is done, the router will update the location property with the new URL.
+
+That was intense--a lot of information! But we learned quite a few things. We learned about the core operations of the Angular router: applying redirects, state recognition, running guards and resolving data, component activation, and navigation. Finally, we looked at an e2e example showing the router in action.
+
+In the rest of this book we will discuss the same operations one more time in much greater depth.
\ No newline at end of file
diff --git a/5_url.md b/5_url.md
new file mode 100644
index 0000000..11858e3
--- /dev/null
+++ b/5_url.md
@@ -0,0 +1,103 @@
+# Chapter 3: URLs
+
+When using the Angular router, a URL is just a serialized router state. Any state transition results in a URL change, and any URL change results in a state transition. Consequently, any link or navigation creates a URL.
+
+## Simple URL
+
+Let's start with this simple URL `'/inbox/33'`.
+
+This is how the router will encode the information about this URL.
+
+```javascript
+const url: UrlSegment[] = [
+ {path: 'inbox', params: {}},
+ {path: '33', params: {}}
+];
+```
+
+Where UrlSegment is defined as follows:
+
+```javascript
+interface UrlSegment {
+ path: string;
+ params: {[name:string]:string};
+}
+```
+
+We can use the ActivatedRoute object to get the URL segments consumed by the route.
+
+```javascript
+class MessageCmp {
+ constructor(r: ActivatedRoute) {
+ r.url.forEach((u: UrlSegment[]) => {
+ //...
+ });
+ }
+}
+```
+
+## Params
+
+Let's soup it up a little by adding matrix or route-specific parameters, so the result URL looks like this: `'/inbox;a=v1/33;b1=v1;b2=v2'`.
+
+```javascript
+[
+ {path: 'inbox', params: {a: 'v1'}},
+ {path: '33', params: {b1: 'v1', b2: 'v2'}}
+]
+```
+
+Matrix parameters are scoped to a particular URL segment. Because of this, there is no risk of name collisions.
+
+## Query Params
+
+Sometimes, however, you want to share some parameters across many activated routes, and that's what query params are for. For instance, given this URL `'/inbox/33?token=23756'`, we can access 'token' in any component:
+
+```javascript
+class ConversationCmp {
+ constructor(r: ActivateRoute) {
+ r.queryParams.forEach((p) => {
+ const token = p['token']
+ });
+ }
+}
+```
+
+Since query parameters are not scoped, they should not be used to store route-specific information.
+
+The fragment (e.g., `'/inbox/33#fragment'`) is similar to query params.
+
+```javascript
+class ConversationCmp {
+ constructor(r: ActivatedRoute) {
+ r.fragment.forEach((f:string) => {
+
+ });
+ }
+}
+```
+
+## Secondary Segments
+
+Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a serialized tree. In all the examples so far every segment had only one child. For instance in `'/inbox/33'` the '33' segment is a child of 'inbox', and 'inbox' is a child of the '/' root segment. We called such children 'primary'. Now look at this example:
+
+ /inbox/33(popup:message/44)
+
+Here the root has two children 'inbox' and 'message'.
+
+{width=60%}
+
+
+The router encodes multiple secondary children using a '//'.
+
+ /inbox/33(popup:message/44//help:overview)
+
+{width=80%}
+
+
+If some other segment, not the root, has multiple children, the router will encode it as follows:
+
+ /inbox/33/(messages/44//side:help)
+
+{width=60%}
+
\ No newline at end of file
diff --git a/6_matching.md b/6_matching.md
new file mode 100644
index 0000000..1417ac6
--- /dev/null
+++ b/6_matching.md
@@ -0,0 +1,350 @@
+# Chapter 4: URL Matching
+
+At the core of the Angular router lies a powerful URL matching engine, which transforms URLs and converts them into router states. Understanding how this engine works is important for implementing advanced use cases.
+
+Once again, let's use this configuration.
+
+```javascript
+[
+ { path: '', pathMatch: 'full', redirectTo: '/inbox' },
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ ]
+ },
+ {
+ path: 'compose',
+ component: ComposeCmp,
+ outlet: 'popup'
+ },
+ {
+ path: 'message/:id',
+ component: PopupMessageCmp,
+ outlet: 'popup'
+ }
+]
+```
+
+
+First, note that every route is defined by two key parts:
+
+* How it matches the URL.
+* What it does once the URL is matched.
+
+*Is is important that the second concern, the action, does not affect the matching.*
+
+And let's say we are navigating to `'/inbox/33/messages/44'`.
+
+This is how matching works:
+
+The router goes through the provided array of routes, one by one, checking if the unconsumed part of the URL starts with a route's path.
+
+Here it checks that `'/inbox/33/messages/44'` starts with `:folder`. It does. So the router sets the folder parameter to 'inbox', then it takes the children of the matched route, the rest of the URL, which is `'33/messages/44'`, and carries on matching.
+
+The router will check that `'33/messages/44'` starts with '', and it does, since we interpret every string to begin with the empty string. Unfortunately, the route does not have any children and we haven't consumed the whole URL. So the router will backtrack to try the next route `path: ':id'`.
+
+This one will work. The id parameter will be set to '33', and finally the `messages/:id` route will be matched, and the second id parameter will be set to '44'.
+
+## Backtracking
+
+Let's illustrate backtracking one more time. If the taken path through the configuration does not “consume” the whole url, the router backtracks to try an alternative path.
+
+Say we have this configuration:
+
+```javascript
+[
+ {
+ path: 'a',
+ children: [
+ {
+ path: 'b',
+ component: ComponentB
+ }
+ ]
+ },
+ {
+ path: ':folder',
+ children: [
+ {
+ path: 'c',
+ component: ComponentC
+ }
+ ]
+ }
+]
+```
+
+When navigating to `'/a/c'`, the router will start with the first route. The `'/a/c'` URL starts with `"path: 'a'"`, so the router will try to match `/c` with `b`. Because it is unable to do that, it will backtrack and will match `'a'` with `":folder"`, and then `'c'` with `"c"`.
+
+## Depth-First
+
+The router doesn't try to find the best match, i.e. it does not have any notion of specificity. It is satisfied with the first one that consumes the whole URL.
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: 'b',
+ component: ComponentB1
+ }
+ ]
+ },
+ {
+ path: 'a',
+ children: [
+ {
+ path: 'b',
+ component: ComponentB2
+ }
+ ]
+ }
+]
+```
+
+When navigating to `'/a/b'`, the first route will be matched even though the second one appears to be 'specific'.
+
+## Wildcards
+
+We have seen that path expressions can contain two types of segments:
+
+* constant segments (e.g., `path: 'messages'`)
+* variable segments (e.g., `path: ':folder'`)
+
+Using just these two we can handle most use cases. Sometimes, however, what we want is the "otherwise" route. The route that will match against any provided URL. That's what wildcard routes are. In the example below we have a wildcard route `{ path: '**', redirectTo: '/notfound' }` that will match any URL that we were not able to match otherwise and will activate `NotFoundCmp`.
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ ]
+ }
+ { path: '**', component: NotFoundCmp }
+]
+```
+
+The wildcard route will "consume" all the URL segments, so `NotFoundCmp` can access those via the injected `ActivatedRoute`.
+
+## Empty-Path Routes
+
+If you look at our configuration once again, you will see that some routes have the path set to an empty string. What does it mean?
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ }
+ ]
+ }
+]
+```
+
+By setting 'path' to an empty string, we create a route that instantiates a component but does not “consume” any URL segments. This means that if we navigate to `'/inbox'`, the router will do the following:
+
+First, it will check that `/inbox` starts with `:folder`, which it does. So it will take what is left of the URL, which is '', and the children of the route. Next, it will check that '' starts with '', which it does! So the result of all this is the following router state:
+
+{width=40%}
+
+
+Empty path routes can have children, and, in general, behave like normal routes. The only special thing about them is that they inherit matrix parameters of their parents. This means that this URL `/inbox;expand=true` will result in the router state where two activated routes have the expand parameter set to true.
+
+{width=40%}
+
+
+## Matching Strategies
+
+By default the router checks if the URL starts with the path property of a route, i.e., it checks if the URL is prefixed with the path. This is an implicit default, but we can set this strategy explicitly, as follows:
+
+```javascript
+// identical to {path: 'a', component: ComponentA}
+{path: 'a', pathMatch: 'prefix', component: ComponentA}
+```
+
+The router supports a second matching strategy--full, which checks that the path is "equal" to what is left in the URL. This is mostly important for redirects. To see why, let's look at this example:
+
+```javascript
+[
+ { path: '', redirectTo: '/inbox' },
+ {
+ path: ':folder',
+ children: [
+ ...
+ ]
+ }
+]
+```
+
+Because the default matching strategy is prefix, and any URL starts with an empty string, the router will always match the first route. Even if we navigate to `'/inbox'`, the router will apply the first redirect. Our intent, however, is to match the second route when navigating to `'/inbox'`, and redirect to `'/inbox'` when navigating to `'/'`. Now, if we change the matching strategy to 'full', the router will apply the redirect only when navigating to `'/'`.
+
+## Componentless Routes
+
+Most of the routes in the configuration have either the redirectTo or component properties set, but some have neither. For instance, look at `"path: ':folder'"` route in the configuration below.
+
+```javascript
+{
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ ]
+}
+```
+
+We called such routes 'componentless' routes. Their main purpose is to consume URL segments, provide some data to its children, and do it without instantiating any components.
+
+The parameters captured by a componentless route will be merged into their children's parameters. The data resolved by a componentless route will be merged as well. In this example, both the child routes will have the folder parameter in their parameters maps.
+
+This particular example could have been easily rewritten as follows:
+
+```javascript
+[
+ {
+ path: ':folder',
+ component: ConversationsCmp
+ },
+ {
+ path: ':folder/:id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+]
+```
+
+We have to duplicate the `:folder` parameter, but overall it works. Sometimes, however, there is no other good option but to use a componentless route.
+
+### Sibling Components Using Same Data
+
+For instance, it is useful to share parameters between sibling components.
+
+In the following example we have two components--`MessageListCmp` and `MessageDetailsCmp`--that we want to put next to each other, and both of them require the message id parameter. `MessageListCmp` uses the id to highlight the selected message, and MessageDetailsCmp uses it to show the information about the message.
+
+One way to model that would be to create a bogus parent component, which both `MessageListCmp` and `MessageDetailsCmp` can get the id parameter from, i.e. we can model this solution with the following configuration:
+
+```javascript
+[
+ {
+ path: 'messages/:id',
+ component: MessagesParentCmp,
+ children: [
+ {
+ path: '',
+ component: MessageListCmp
+ },
+ {
+ path: '',
+ component: MessageDetailsCmp,
+ outlet: 'details'
+ }
+ ]
+ }
+]
+```
+
+With this configuration in place, navigating to `'/messages/11'` will result in this component tree:
+
+{width=80%}
+
+
+This solution has a problem--we need to create the bogus component, which serves no real purpose. That's where componentless routes are a good solution:
+
+```javascript
+[
+ {
+ path: 'messages/:id',
+ children: [
+ {
+ path: '',
+ component: MessageListCmp
+ },
+ {
+ path: '',
+ component: MessageDetailsCmp,
+ outlet: 'details'
+ }
+ ]
+ }
+]
+```
+
+Now, when navigating to `'/messages/11'`, the router will create the following component tree:
+
+{width=80%}
+
+
+## Composing Componentless and Empty-path Routes
+
+What is really exciting about all these features is that they compose very nicely. So we can use them together to handle advanced use cases in just a few lines of code.
+
+Let me give you an example. We have learned that we can use empty-path routes to instantiate components without consuming any URL segments, and we can use componentless routes to consume URL segments without instantiating components. What about combining them?
+
+```javascript
+[
+ {
+ path: '',
+ canActivate: [CanActivateMessagesAndContacts],
+ resolve: {
+ token: TokenNeededForBothMessagsAndContacts
+ },
+
+ children: [
+ {
+ path: 'messages',
+ component: MesssagesCmp
+ },
+ {
+ path: 'contacts',
+ component: ContactsCmp
+ }
+ ]
+ }
+]
+```
+
+Here we have defined a route that neither consumes any URL segments nor creates any components, but used merely for running guards and fetching data that will be used by both `MesssagesCmp` and `ContactsCmp`. Duplicating these in the children is not an option as both the guard and the data resolver can be expensive asynchronous operations and we want to run them only once.
+
+## Summary
+
+We've learned a lot! First, we talked about how the router does matching. It goes through the provided routes, one by one, checking if the URL starts with a route's path. Then, we learned that the router does not have any notion of specificity. It just traverses the configuration in the depth-first order, and it stops after finding the path matching the whole URL, i.e., the order of routes in the configuration matters. After that, we talked about empty-path routes that do not consume any URL segments, and about componentless routes that do not instantiate any components. We showed how we can use them to handle advanced use cases.
\ No newline at end of file
diff --git a/7_redirects.md b/7_redirects.md
new file mode 100644
index 0000000..6e6004a
--- /dev/null
+++ b/7_redirects.md
@@ -0,0 +1,140 @@
+# Chapter 5: Redirects
+
+
+
+Using redirects we can transform the URL before the router creates a router state out of it. This is useful for normalizing URLs and large scale refactorings.
+
+## Local and Absolute Redirects
+
+Redirects can be local and absolute. Local redirects replace a single URL segment with a different one. Absolute redirects replace the whole URL.
+
+If the 'redirectTo' value starts with a '/', then it is an absolute redirect. The next example shows the difference between relative and absolute redirects.
+
+```javascript
+[
+ {
+ path: ':folder/:id',
+ component: ConversationCmp,
+ children: [
+ {
+ path: 'contacts/:name',
+ redirectTo: '/contacts/:name'
+ },
+ {
+ path: 'legacy/messages/:id',
+ redirectTo: 'messages/:id'
+ },
+ {
+ path: 'messages/:id',
+ component: MessageCmp
+ }
+ ]
+ },
+ {
+ path: 'contacts/:name',
+ component: ContactCmp
+ }
+]
+```
+
+When navigating to `'/inbox/33/legacy/messages/44'`, the router will apply the second redirect and will change the URL to `'/inbox/33/messages/44'`. In other words, the part of the URL corresponding to the matched segment will be replaced. But navigating to `'/inbox/33/contacts/jim'` will replace the whole URL with `'/contacts/jim'`.
+
+Note that a redirectTo value can contain variable segments captured by the path expression (e.g., ':name', ':id'). All the matrix parameters of the corresponding segments matched by the path expression will be preserved as well.
+
+## One Redirect at a Time
+
+You can set up redirects at different levels of your router configuration. Let's modify the example from above to illustrate this.
+
+```javascript
+[
+ {
+ path: 'legacy/:folder/:id',
+ redirectTo: ':folder/:id'
+ },
+ {
+ path: ':folder/:id',
+ component: ConversationCmp,
+ children: [
+ {
+ path: 'legacy/messages/:id',
+ redirectTo: 'messages/:id'
+ },
+ {
+ path: 'messages/:id',
+ component: MessageCmp
+ }
+ ]
+ }
+]
+```
+
+When navigating to `'/legacy/inbox/33/legacy/messages/44'`, the router will first apply the outer redirect, transforming the URL to `'/inbox/33/legacy/messages/44'`. After that the router will start processing the children of the second route and will apply the inner redirect, resulting in this URL: `'/inbox/33/messages/44'`.
+
+One constraint the router imposes is at any level of the configuration the router applies only one redirect, i.e., redirects cannot be chained.
+
+For instance, say we have this configuration.
+
+```javascript
+[
+ {
+ path: 'legacy/messages/:id',
+ redirectTo: 'messages/:id'
+ },
+ {
+ path: 'messages/:id',
+ redirectTo: 'new/messages/:id'
+ },
+ {
+ path: 'new/messages/:id',
+ component: MessageCmp
+ }
+]
+```
+
+When navigating to `'legacy/messages/:id'`, the router will replace the URL with `'messages/:id'` and will stop there. It won't redirect to `'new/messages/:id'`. A similar constraint is applied to absolute redirects: once an absolute redirect is matched, the redirect phase stops.
+
+## Using Redirects to Normalize URLs
+
+We often use redirects for URL normalization. Say we want both `mail-app.vsavkin.com` and `mail-app.vsavkin.com/inbox` render the same UI. We can use a redirect to achieve that:
+
+```javascript
+[
+ { path: '', pathMatch: 'full', redirectTo: '/inbox' },
+ {
+ path: ':folder',
+ children: [
+ ...
+ ]
+ }
+]
+```
+
+We can also use redirects to implement a not-found page.
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ { path: '**', redirectTo: '/notfound/conversation' }
+ ]
+ }
+ { path: 'notfound/:objectType', component: NotFoundCmp }
+]
+```
+
+## Using Redirects to Enable Refactoring
+
+Another big use case for using redirects is to enable large scale refactorings. Such refactorings can take months to complete, and, consequently, we will not be able to update all the URLs in the whole application in one go. We will need to do in phases. By using redirects we can keep the old URLs working while migrating to the new implementation.
\ No newline at end of file
diff --git a/8_routerstate.md b/8_routerstate.md
new file mode 100644
index 0000000..22163db
--- /dev/null
+++ b/8_routerstate.md
@@ -0,0 +1,281 @@
+# Chapter 6: Router State
+
+
+
+During a navigation, after redirects have been applied, the router creates a `RouterStateSnapshot`.
+
+## What is RouterStateSnapshot?
+
+```javascript
+interface RouterStateSnapshot {
+ root: ActivatedRouteSnapshot;
+}
+
+interface ActivatedRouteSnapshot {
+ url: UrlSegment[];
+ params: {[name:string]:string};
+ data: {[name:string]:any};
+
+ queryParams: {[name:string]:string};
+ fragment: string;
+
+ root: ActivatedRouteSnapshot;
+ parent: ActivatedRouteSnapshot;
+ firstchild: ActivatedRouteSnapshot;
+ children: ActivatedRouteSnapshot[];
+}
+```
+
+As you can see `RouterStateSnapshot` is a tree of activated route snapshots. Every node in this tree knows about the "consumed" URL segments, the extracted parameters, and the resolved data. To make it clearer, let's look at this example:
+
+```javascript
+[
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ {
+ path: 'messages',
+ component: MessagesCmp
+ },
+ {
+ path: 'messages/:id',
+ component: MessageCmp,
+ resolve: {
+ message: MessageResolver
+ }
+ }
+ ]
+ }
+ ]
+ }
+]
+```
+
+When we are navigating to `'/inbox/33/messages/44'`, the router will look at the URL and will construct the following `RouterStateSnapshot`:
+
+{width=40%}
+
+
+After that the router will instantiate `ConversationCmp` with `MessageCmp` in it.
+
+Now imagine we are navigating to a different URL: `'/inbox/33/messages/45'`, which will result in the following snapshot:
+
+{width=40%}
+
+
+To avoid unnecessary DOM modifications, the router will reuse the components when the parameters of the corresponding routes change. In this example, the id parameter of the message component has changed from 44 to 45. This means that we cannot just inject an `ActivatedRouteSnapshot` into `MessageCmp` because the snapshot will always have the id parameter set to 44, i.e., it will get stale.
+
+The router state snapshot represents the state of the application at a moment in time, hence the name 'snapshot'. But components can stay active for hours, and the data they show can change. So having only snapshots won't cut it--we need a data structure that allows us to deal with changes.
+
+Introducing RouterState!
+
+```javascript
+interface RouterState {
+ snapshot: RouterStateSnapshot; //returns current snapshot
+
+ root: ActivatedRoute;
+}
+
+interface ActivatedRoute {
+ snapshot: ActivatedRouteSnapshot; //returns current snapshot
+
+ url: Observable;
+ params: Observable<{[name:string]:string}>;
+ data: Observable<{[name:string]:any}>;
+
+ queryParams: Observable<{[name:string]:string}>;
+ fragment: Observable;
+
+ root: ActivatedRout;
+ parent: ActivatedRout;
+ firstchild: ActivatedRout;
+ children: ActivatedRout[];
+}
+```
+
+`RouterState` and `ActivatedRoute` are similar to their snapshot counterparts except that they expose all the values as observables, which are great for dealing with values changing over time.
+
+Any component instantiated by the router can inject its `ActivatedRoute`.
+
+```javascript
+@Component({
+ template: `
+ Title: {{(message|async).title}}
+ ...
+ `
+})
+class MessageCmp {
+ message: Observable;
+ constructor(r: ActivatedRoute) {
+ this.message = r.data.map(d => d.message);
+ }
+}
+```
+
+If we navigate from `'/inbox/33/messages/44'` to `'/inbox/33/messages/45'`, the data observable will emit a new set of data with the new message object, and the component will display Message 45.
+
+## Accessing Snapshots
+
+The router exposes parameters and data as observables, which is convenient most of the time, but not always. Sometimes what we want is a snapshot of the state that we can examine at once.
+
+```javascript
+@Component({...})
+class MessageCmp {
+ constructor(r: ActivatedRoute) {
+ r.url.subscribe(() => {
+ r.snapshot; // any time url changes, this callback is fired
+ });
+ }
+}
+```
+
+## ActivatedRoute
+
+`ActivatedRoute` provides access to the url, params, data, queryParams, and fragment observables. We will look at each of them in detail, but first let's examine the relationships between them.
+
+URL changes are the source of any changes in a route. And it has to be this way as the user has the ability to modify the location directly.
+
+Any time the URL changes, the router derives a new set of parameters from it: the router takes the positional parameters (e.g., ':id') of the matched URL segments and the matrix parameters of the last matched URL segment and combines those. This operation is pure: the URL has to change for the parameters to change. Or in other words, the same URL will always result in the same set of parameters.
+
+Next, the router invokes the route's data resolvers and combines the result with the provided static data. Since data resolvers are arbitrary functions, the router cannot guarantee that you will get the same object when given the same URL. Even more, often this cannot be the case! The URL contains the id of a resource, which is fixed, and data resolvers fetch the content of that resource, which often varies over time.
+
+Finally, the activated route provides the queryParams and fragment observables. In opposite to other observables, that are scoped to a particular route, query parameters and fragment are shared across multiple routes.
+
+### URL
+
+Given the following:
+
+```javascript
+@Component({...})
+class ConversationCmp {
+ constructor(r: ActivatedRoute) {
+ r.url.subscribe((s:UrlSegment[]) => {
+ console.log("url", s);
+ });
+ }
+}
+```
+
+And navigating first to `'/inbox/33/messages/44'` and then to `'/inbox/33/messages/45'`, we will see:
+
+```
+url [{path: 'messages', params: {}}, {path: '44', params: {}}]
+url [{path: 'messages', params: {}}, {path: '45', params: {}}]
+```
+
+We do not often listen to URL changes as those are too low level. One use case where it can be practical is when a component is activated by a wildcard route. Since in this case the array of URL segments is not fixed, it might be useful to examine it to show different data to the user.
+
+
+### Params
+
+Given the following:
+
+```javascript
+@Component({...})
+class MessageCmp {
+ constructor(r: ActivatedRoute) {
+ r.params.subscribe((p => {
+ console.log("params", params);
+ });
+ }
+}
+```
+
+And when navigating first to `'/inbox/33/messages;a=1/44;b=1'` and then to `'/inbox/33/messages;a=2/45;b=2'`, we will see
+
+```
+params {id: '44', b: '1'}
+params {id: '45', b: '2'}
+```
+
+First thing to note is that the id parameter is a string (when dealing with URLs we always work with strings). Second, the route gets only the matrix parameters of its last URL segment. That is why the 'a' parameter is not present.
+
+### Data
+
+Let's tweak the configuration from above to see how the data observable works.
+
+```javascript
+{
+ path: 'messages/:id',
+ component: MessageCmp,
+ data: {
+ allowReplyAll: true
+ },
+ resolve: {
+ message: MessageResolver
+ }
+}
+```
+
+Where `MessageResolver` is defined as follows:
+
+```javascript
+class MessageResolver implements Resolve {
+ constructor(private repo: ConversationsRepo, private currentUser: User) {}
+
+ resolve(route: ActivatedRouteSnapshot, state: RouteStateSnapshot):
+ Promise {
+ return this.repo.fetchMessage(route.params['id'], this.currentUser);
+ }
+}
+```
+
+The data property is used for passing a fixed object to an activated route. It does not change throughout the lifetime of the application. The resolve property is used for dynamic data.
+
+Note that in the configuration above the line `"message: MessageResolver"` does not tell the router to instantiate the resolver. It instructs the router to fetch one using dependency injection. This means that you have to register `MessageResolver` in the list of providers somewhere.
+
+Once the router has fetched the resolver, it will call the 'resolve' method on it. The method can return a promise, an observable, or any other object. If the return value is a promise or an observable, the router will wait for that promise or observable to complete before proceeding with the activation.
+
+The resolver does not have to be a class implementing the `Resolve` interface. It can also be a function:
+
+```javascript
+function resolver(route: ActivatedRouteSnapshot, state: RouteStateSnapshot):
+ Promise {
+ return repo.fetchMessage(route.params['id'], this.currentUser);
+}
+```
+
+The router combines the resolved and static data into a single property, which you can access, as follows:
+
+```javascript
+@Component({...})
+class MessageCmp {
+ constructor(r: ActivatedRoute) {
+ r.data.subscribe((d => {
+ console.log('data', d);
+ });
+ }
+}
+```
+
+When navigating first to `'/inbox/33/message/44'` and then to `'/inbox/33/messages/45'`, we will see
+
+```
+data {allowReplyAll: true, message: {id: 44, title: 'Rx Rocks', ...}}
+data {allowReplyAll: true, message: {id: 45, title: 'Angular Rocks', ...}}
+```
+
+## Query Params and Fragment
+
+In opposite to other observables, that are scoped to a particular route, query parameters and fragment are shared across multiple routes.
+
+```javascript
+@Component({...})
+class MessageCmp {
+ debug: Observable;
+ fragment: Observable;
+
+ constructor(route: ActivatedRoute) {
+ this.debug = route.queryParams.map(p => p.debug);
+ this.fragment = route.fragment;
+ }
+}
+```
\ No newline at end of file
diff --git a/9_navigation.md b/9_navigation.md
new file mode 100644
index 0000000..2cb460a
--- /dev/null
+++ b/9_navigation.md
@@ -0,0 +1,324 @@
+# Chapter 7: Links and Navigation
+
+
+
+The primary job of the router is to manage navigation between different router states. There are two ways to accomplish this: imperatively, by calling `router.navigate`, or declaratively, by using the `RouterLink` directive.
+
+As before, let's assume the following configuration:
+
+```javascript
+[
+ { path: '', pathMatch: 'full', redirectTo: '/inbox' },
+ {
+ path: ':folder',
+ children: [
+ {
+ path: '',
+ component: ConversationsCmp
+ },
+ {
+ path: ':id',
+ component: ConversationCmp,
+ children: [
+ { path: 'messages', component: MessagesCmp },
+ { path: 'messages/:id', component: MessageCmp }
+ ]
+ }
+ ]
+ },
+ {
+ path: 'compose',
+ component: ComposeCmp,
+ outlet: 'popup'
+ },
+ {
+ path: 'message/:id',
+ component: PopupMessageCmp,
+ outlet: 'popup'
+ }
+]
+```
+
+## Imperative Navigation
+
+To navigate imperatively, inject the Router service and call `navigate` or `navigateByUrl` on it. Why two methods and not one?
+
+Using `router.navigateByUrl` is similar to changing the location bar directly--we are providing the "whole" new URL. Whereas `router.navigate` creates a new URL by applying a series of passed-in commands, a patch, to the current URL.
+
+To see the difference clearly, imagine that the current URL is `'/inbox/11/messages/22(popup:compose)'`.
+
+With this URL, calling `router.navigateByUrl('/inbox/33/messages/44')` will result in
+`'/inbox/33/messages/44'`, and calling `router.navigate('/inbox/33/messages/44')` will result in
+ `'/inbox/33/messages/44(popup:compose)'`.
+
+### Router.navigate
+
+Let's see what we can do with `router.navigate`.
+
+
+####Passing an array or a string
+
+Passing a string is sugar for passing an array with a single element.
+
+```javascript
+router.navigate('/inbox/33/messages/44')
+```
+
+is sugar for
+
+```javascript
+router.navigate(['/inbox/33/messages/44'])
+```
+
+which itself is sugar for
+
+```javascript
+router.navigate(['/inbox', 33, 'messages', 44])
+```
+
+####Passing matrix params
+
+```javascript
+router.navigate([
+ '/inbox', 33, {details: true}, 'messages', 44, {mode: 'preview'}
+])
+```
+
+navigates to
+
+```javascript
+'/inbox/33;details=true/messages/44;mode=preview(popup:compose)'
+```
+
+#### Updating secondary segments
+
+```javascript
+router.navigate([{outlets: {popup: 'message/22'])
+```
+navigates to
+
+```javascript
+'/inbox/11/messages/22(popup:message/22)'
+```
+
+We can also update multiple segments at once, as follows:
+
+```javascript
+router.navigate([
+ {outlets: {primary: 'inbox/33/messages/44', popup: 'message/44'}}
+])
+```
+
+navigates to
+
+```javascript
+'/inbox/33/messages/44(popup:message/44)'
+```
+
+And, of course, this works for any segment, not just the root one.
+
+```javascript
+router.navigate([
+ '/inbox/33', {outlets: {primary: 'messages/44', help: 'message/123'}}
+])
+```
+
+navigates to
+
+```javascript
+'/inbox/33/(messages/44//help:messages/123)(popup:message/44)'
+```
+
+We can also remove segments by setting them to 'null'.
+
+```javascript
+router.navigate([{outlets: {popup: null])
+```
+
+navigates to
+
+```javascript
+'/inbox/11/messages/22'
+```
+
+####Relative Navigation
+
+By default, the navigate method applies the provided commands starting from the root URL segment, i.e., the navigation is absolute. We can make it relative by providing the starting route, like this:
+
+```javascript
+@Component({...})
+class MessageCmp {
+ constructor(private route: ActivatedRoute, private router: Router) {}
+
+ goToConversation() {
+ this.router.navigate('../../', {relativeTo: this.route});
+ }
+}
+```
+
+Let's look at a few examples, given we are providing the `"path: 'message/:id'"` route.
+
+```javascript
+router.navigate('details', {relativeTo: this.route})
+```
+
+navigates to
+
+```javascript
+'/inbox/33/messages/44/details(popup:compose)'
+```
+
+The '../' allows us to skip one URL segment.
+
+```javascript
+router.navigate('../55', {relativeTo: this.route})
+```
+
+navigates to
+
+```javascript
+'/inbox/33/messages/55(popup:compose)'
+```
+
+```javascript
+router.navigate('../../', {relativeTo: this.route})
+```
+
+navigates to
+
+```javascript
+'/inbox/33(popup:compose)'
+```
+
+
+####Forcing Absolute Navigation
+
+If the first command starts with a slash, the navigation is absolute regardless if we provide a route or not.
+
+
+####Navigation is URL-Based
+
+Using '../' does not skip a route, but skips a URL segment. More generally, the router configuration has no affect on URL-generation. The router only looks at the current URL and the provided commands to generate a new URL.
+
+
+####Passing Query Params and Fragment
+
+By default the router resets query params during navigation. If this is the current URL:
+
+```javascript
+'/inbox/11/messages/22?debug=true#section2'
+```
+
+Then calling
+
+```javascript
+router.navigate('/inbox/33/message/44')
+```
+
+will navigate to
+
+```javascript
+'/inbox/33/messages/44'
+```
+
+If we want to preserve the current query params and fragment, we can do the following:
+
+```javascript
+router.navigate('/inbox/33/message/44',
+ {preserveQueryParams: true, preserveFragment: true})
+```
+
+Or we always can provide new params and fragment, like this:
+
+```javascript
+router.navigate('/inbox/33/message/44',
+ {queryParams: {debug: false}, fragment: 'section3'})
+```
+
+
+### RouterLink
+
+Another way to navigate around is by using the `RouterLink` directive.
+
+```javascript
+@Component({
+ template: `
+ Open Message 44
+ `
+})
+class SomeComponent {}
+```
+
+Behind the scenes `RouterLink` just calls `router.navigate` with the provided commands. If we do not start the first command with a slash, the navigation is relative to the route of the component.
+
+Everything that we can pass to `router.navigate`, we can pass to `routerLink`. For instance:
+
+```html
+
+ Open Message 44
+
+```
+
+As with `router.navigate`, we can set or preserve query params and fragment.
+
+```html
+
+ Open Message 44
+
+
+
+ Open Message 44
+
+```
+
+This directive will also update the href attribute when applied to an `` link element, so it is SEO friendly and the right-click open-in-new-browser-tab behavior we expect from regular links will work.
+
+### Active Links
+
+By using the `RouterLinkActive` directive, we can add a CSS class to an element when the link's route becomes active.
+
+```html
+Inbox
+```
+
+When the URL is either `'/inbox'` or `'/inbox/33'`, the active-link class will be added to the `a` tag. If the url changes, the class will be removed.
+
+We can set more than one class, as follows:
+
+```html
+Inbox
+
+Inbox
+```
+
+
+####Exact Matching
+
+We can make the matching exact by passing `"{exact: true}"`. This will add the classes only when the URL matches the link exactly. For instance, in the following example the 'active-link' class will be added only when the URL is `'/inbox'`, not `'/inbox/33'`.
+
+```html
+
+ Inbox
+
+```
+
+####Adding Classes to Ancestors
+
+Finally, we can apply this directive to an ancestor of a `RouterLink`.
+
+```html
+
+```
+
+This will set the 'active-link' class on the div tag if the URL is either '/inbox' or '/drafts'.
+
+## Summary
+
+That's a lot of information! So let's recap.
+
+First, we established that the primary job of the router is to manage navigation. And there are two ways to do it: imperatively, by calling `router.navigate`, or declaratively, by using the RouterLink directive. We learned about the difference between `router.navigateByUrl` and `router.navigate`: one takes the whole URL, and the other one takes a patch it applies to the current URL. Then we talked about absolute and relative navigation. Finally, we saw how to use `[routerLink]` and `[routerLinkActive]` to set up navigation in the template.
\ No newline at end of file