diff --git a/public/docs/_examples/toh-5/ts/src/app/hero-detail.component.1.ts b/public/docs/_examples/toh-5/ts/src/app/hero-detail.component.1.ts index 6713ce4dc7..2f5081bdce 100644 --- a/public/docs/_examples/toh-5/ts/src/app/hero-detail.component.1.ts +++ b/public/docs/_examples/toh-5/ts/src/app/hero-detail.component.1.ts @@ -3,7 +3,7 @@ // is solely for containing the transitory state of the imports. // #docregion added-imports -// Keep the Input import for now, we'll remove it later: +// Keep the Input import for now, you'll remove it later: import { Component, Input, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; import { Location } from '@angular/common'; diff --git a/public/docs/_examples/toh-5/ts/src/app/heroes.component.css b/public/docs/_examples/toh-5/ts/src/app/heroes.component.css index 35e45af98d..b49fa0a419 100644 --- a/public/docs/_examples/toh-5/ts/src/app/heroes.component.css +++ b/public/docs/_examples/toh-5/ts/src/app/heroes.component.css @@ -1,3 +1,4 @@ +/* #docregion */ .selected { background-color: #CFD8DC !important; color: white; diff --git a/public/docs/ts/latest/tutorial/toh-pt4.jade b/public/docs/ts/latest/tutorial/toh-pt4.jade index 40c357ecbf..c312124ab6 100644 --- a/public/docs/ts/latest/tutorial/toh-pt4.jade +++ b/public/docs/ts/latest/tutorial/toh-pt4.jade @@ -92,7 +92,7 @@ code-example(language="sh" class="code-shell"). :marked ### Getting hero data - Add a `getHeroes` method stub. + Add a `getHeroes()` method stub. +makeExample('toh-4/ts/src/app/hero.service.1.ts', 'getHeroes-stub', 'src/app/hero.service.ts (getHeroes stub)')(format=".") @@ -117,7 +117,7 @@ code-example(language="sh" class="code-shell"). +makeExample('toh-4/ts/src/app/app.component.1.ts', 'heroes-prop', 'src/app/app.component.ts (heroes property)')(format=".") :marked ### Return mocked hero data - Back in the `HeroService`, import the mock `HEROES` and return it from the `getHeroes` method. + Back in the `HeroService`, import the mock `HEROES` and return it from the `getHeroes()` method. The `HeroService` looks like this: +makeExample('toh-4/ts/src/app/hero.service.1.ts', 'full', 'src/app/hero.service.ts')(format=".") @@ -184,7 +184,7 @@ code-example(format="nocode"). The `AppComponent`, as well as its child components, can use that service to get hero data. a#child-component :marked - ### *getHeroes* in the *AppComponent* + ### *getHeroes()* in the *AppComponent* The service is in a `heroService` private variable. You could call the service and get the data in one line. @@ -198,12 +198,12 @@ a#child-component ### The *ngOnInit* lifecycle hook `AppComponent` should fetch and display hero data with no issues. - You might be tempted to call the `getHeroes` method in a constructor, but + You might be tempted to call the `getHeroes()` method in a constructor, but a constructor should not contain complex logic, especially a constructor that calls a server, such as as a data access method. The constructor is for simple initializations, like wiring constructor parameters to properties. - To have Angular call `getHeroes`, you can implement the Angular *ngOnInit lifecycle hook*. + To have Angular call `getHeroes()`, you can implement the Angular *ngOnInit lifecycle hook*. Angular offers interfaces for tapping into critical moments in the component lifecycle: at creation, after each change, and at its eventual destruction. @@ -221,7 +221,7 @@ code-example(format="nocode"). export class AppComponent implements OnInit {} :marked Write an `ngOnInit` method with the initialization logic inside. Angular will call it - at the right time. In this case, initialize by calling `getHeroes`. + at the right time. In this case, initialize by calling `getHeroes()`. +makeExcerpt('toh-4/ts/src/app/app.component.1.ts', 'ng-on-init', 'app/app.component.ts') :marked The app should run as expected, showing a list of heroes and a hero detail view @@ -231,15 +231,17 @@ code-example(format="nocode"). :marked ## Async services and !{_Promise}s The `HeroService` returns a list of mock heroes immediately; - its `getHeroes` signature is synchronous. + its `getHeroes()` signature is synchronous. +makeExample('toh-4/ts/src/app/app.component.1.ts', 'get-heroes')(format=".") :marked Eventually, the hero data will come from a remote server. - When using the remote server, users don't have to wait for the server to respond - and you aren't able to block the UI during the wait. + When using a remote server, users don't have to wait for the server to respond; + additionally, you aren't able to block the UI during the wait. :marked - Instead, you can use *!{_Promise}s*, which is an asynchronous technique that changes the signature of the `getHeroes` method. + To coordinate the view with the response, + you can use *!{_Promise}s*, which is an asynchronous + technique that changes the signature of the `getHeroes()` method. ### The hero service makes a !{_Promise} @@ -253,7 +255,7 @@ code-example(format="nocode"). [Exploring ES6](http://http://exploringjs.com/es6.html). :marked - Update the `HeroService` with this !{_Promise}-returning `getHeroes` method: + Update the `HeroService` with this !{_Promise}-returning `getHeroes()` method: +makeExample('toh-4/ts/src/app/hero.service.ts', 'get-heroes', 'src/app/hero.service.ts (excerpt)')(format=".") :marked You're still mocking the data. You're simulating the behavior of an ultra-fast, zero-latency server, @@ -268,7 +270,7 @@ code-example(format="nocode"). You have to change the implementation to *act on the !{_Promise} when it resolves*. When the !{_Promise} resolves successfully, you'll have heroes to display. - Pass the callback function as an argument to the !{_Promise}'s `then` method: + Pass the callback function as an argument to the !{_Promise}'s `then()` method: +makeExample('toh-4/ts/src/app/app.component.ts', 'get-heroes', 'src/app/app.component.ts (getHeroes - revised)')(format=".") .l-sub-section :marked @@ -334,20 +336,20 @@ code-example(format="nocode"). ## The road ahead The Tour of Heroes has become more reusable using shared components and services. The next goal is to create a dashboard, add menu links that route between the views, and format data in a template. - As the app evolves, you'll learn how to design it to make it easier to grow and maintain. + As the app evolves, you'll discover how to design it to make it easier to grow and maintain. - You learn about Angular component router and navigation among the views in the [next tutorial](toh-pt5.html) page. + Read about the Angular component router and navigation among the views in the [next tutorial](toh-pt5.html) page. .l-main-section :marked ## Appendix: Take it slow To simulate a slow connection, - import the `Hero` symbol and add the following `getHeroesSlowly` method to the `HeroService`. + import the `Hero` symbol and add the following `getHeroesSlowly()` method to the `HeroService`. +makeExample('toh-4/ts/src/app/hero.service.ts', 'get-heroes-slowly', 'app/hero.service.ts (getHeroesSlowly)')(format=".") :marked - Like `getHeroes`, it also returns a !{_Promise}. + Like `getHeroes()`, it also returns a !{_Promise}. But this !{_Promise} waits two seconds before resolving the !{_Promise} with mock heroes. - Back in the `AppComponent`, replace `heroService.getHeroes` with `heroService.getHeroesSlowly` + Back in the `AppComponent`, replace `getHeroes()` with `getHeroesSlowly()` and see how the app behaves. diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index 0981cf4d2c..29c9bac19c 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -12,8 +12,8 @@ block includes * Add a *Dashboard* view. * Add the ability to navigate between the *Heroes* and *Dashboard* views. - * When users click a hero name in either view, they should navigate to a detail view of the selected hero. - * When users click a *deep link* in an email, the detail view for a particular hero should open. + * When users click a hero name in either view, navigate to a detail view of the selected hero. + * When users click a *deep link* in an email, open the detail view for a particular hero. When you’re done, users will be able to navigate the app like this: @@ -37,7 +37,6 @@ figure.image-display :marked ## Where you left off Before continuing with the Tour of Heroes, verify that you have the following structure. - If not, go back to the previous pages. block intro-file-tree .filetree @@ -215,14 +214,14 @@ block router-config-intro :marked ### Make the router available - Add the initial route configuration, `RouterModule`, to the `AppModule` imports !{_array}. + Import the `RouterModule` and add it to the `AppModule` imports !{_array}. +makeExcerpt('src/app/app.module.2.ts (app routing)', '') .l-sub-section :marked - The `forRoot` method is called because a configured router is provided at the app's root. - The `forRoot` method supplies the Router service providers and directives needed for routing, and + The `forRoot()` method is called because a configured router is provided at the app's root. + The `forRoot()` method supplies the Router service providers and directives needed for routing, and performs the initial navigation based on the current browser URL. - var _heroesRoute = _docsFor == 'dart' ? "'Heroes'" : 'heroes' @@ -260,7 +259,7 @@ block routerLink [Routing & Navigation](../guide/router.html#) page. :marked - Refresh the browser. The app title and heroes link, but not the heroes list, display. + Refresh the browser. The browser displays the app title and heroes link, but not the heroes list. .l-sub-section :marked @@ -269,7 +268,7 @@ block routerLink Soon you'll add a route that matches the path `/`. :marked - Click the *Heroes* navigation link. The browser bar updates to `/heroes` + Click the *Heroes* navigation link. The address bar updates to `/heroes` and the list of heroes displays. `AppComponent` now looks like this: @@ -361,13 +360,13 @@ block templateUrl-path-resolution :marked `*ngFor` is used again to iterate over a list of heroes and display their names. - The extra `
` elements will help with styling later in this page. + The extra `
` elements will help with styling later. ### Sharing the *HeroService* To populate the component's `heroes` !{_array}, you can re-use the `HeroService`. - Earlier in the page, you removed the `HeroService` from the `providers` !{_array} of `HeroesComponent` + Earlier, you removed the `HeroService` from the `providers` !{_array} of `HeroesComponent` and added it to the `providers` !{_array} of `!{_AppModuleVsAppComp}`. That move created a singleton `HeroService` instance, available to all components of the app. Angular injects `HeroService` and you can use it in the `DashboardComponent`. @@ -379,7 +378,7 @@ block templateUrl-path-resolution +makeExcerpt('src/app/dashboard.component.ts','imports') :marked - Now implement the `DashboardComponent` class like this: + Now create the `DashboardComponent` class like this: +makeExcerpt('src/app/dashboard.component.ts (class)', 'class') @@ -474,7 +473,7 @@ code-example(format="nocode"). block route-params :marked You'll no longer receive the hero in a parent component property binding. - The new `HeroDetailComponent` should take the `id` parameter from the `params` observable + The new `HeroDetailComponent` should take the `id` parameter from the `params` Observable in the `ActivatedRoute` service and use the `HeroService` to fetch the hero with that `id`. :marked @@ -505,7 +504,7 @@ block route-params block ngOnInit :marked - Inside the `ngOnInit` lifecycle hook, use the `params` observable to + Inside the `ngOnInit` lifecycle hook, use the `params` Observable to extract the `id` parameter value from the `ActivatedRoute` service and use the `HeroService` to fetch the hero with that `id`. @@ -514,11 +513,11 @@ block ngOnInit block extract-id :marked - The `switchMap` operator maps the id in the observable route parameters - to a new `Observable`, the result of the `HeroService.getHero` method. + The `switchMap` operator maps the `id` in the Observable route parameters + to a new `Observable`, the result of the `HeroService.getHero()` method. - If a user re-navigates to this component while a getHero request is still processing, - `switchMap` cancels the old request and then calls `HeroService.getHero` again. + If a user re-navigates to this component while a `getHero` request is still processing, + `switchMap` cancels the old request and then calls `HeroService.getHero()` again. - var _str2int = _docsFor == 'dart' ? 'int.parse static method' : 'JavaScript (+) operator' :marked @@ -534,13 +533,13 @@ block extract-id section of the [Routing & Navigation](../guide/router.html) page, the `Router` manages the observables it provides and localizes the subscriptions. The subscriptions are cleaned up when the component is destroyed, protecting against - memory leaks, so you don't need to unsubscribe from the route params `Observable`. + memory leaks, so you don't need to unsubscribe from the route `params` `Observable`. :marked ### Add *HeroService.getHero* - In the previous code snippet, `HeroService` doesn't have a `getHero` method. To fix this issue, - open `HeroService` and add a `getHero` method that filters the heroes list from `getHeroes` by `id`. + In the previous code snippet, `HeroService` doesn't have a `getHero()` method. To fix this issue, + open `HeroService` and add a `getHero()` method that filters the heroes list from `getHeroes` by `id`. +makeExcerpt('src/app/hero.service.ts', 'getHero') @@ -550,7 +549,7 @@ block extract-id Users have several ways to navigate *to* the `HeroDetailComponent`. To navigate somewhere else, users can click one of the two links in the `AppComponent` or click the browser's back button. - Now add a third option, a `goBack` method that navigates backward one step in the browser's history stack + Now add a third option, a `goBack()` method that navigates backward one step in the browser's history stack using the `Location` service you injected previously. +makeExcerpt('src/app/hero-detail.component.ts', 'goBack') @@ -633,8 +632,8 @@ block extract-id establish key facts about the entire app for the Angular compiler. It's a good idea to refactor the routing configuration into its own class. - The current `RouterModule.forRoot()` produces an Angular `ModuleWithProviders`. - A class dedicated to routing should be a *routing module*. + The current `RouterModule.forRoot()` produces an Angular `ModuleWithProviders`, + a class dedicated to routing should be a *routing module*. For more information, see the [Milestone #2: The Routing Module](../guide/router.html#routing-module) section of the [Routing & Navigation](../guide/router.html) page. @@ -658,8 +657,8 @@ block extract-id ### Update *AppModule* - Delete the routing configuration from `AppModule` and import the `AppRoutingModule` - (*both* with an ES `import` statement *and* by adding it to the `NgModule.imports` list). + Delete the routing configuration from `AppModule` and import the `AppRoutingModule`. + Use an ES `import` statement *and* add it to the `NgModule.imports` list. :marked Here is the revised `AppModule`, compared to its pre-refactor state: @@ -696,9 +695,6 @@ block extract-id Add the following HTML fragment at the bottom of the template where the `` used to be: - - Add the following HTML fragment at the bottom of the template where the `` used to be: - +makeExcerpt('src/app/heroes.component.html', 'mini-detail', 'src/app/heroes.component.ts') @@ -733,41 +729,56 @@ figure.image-display The component file is big. It's difficult to find the component logic amidst the noise of HTML and CSS. - Before making any more changes, migrate the template and styles to their own files. + Before making any more changes, migrate the template and styles to their own files. - 1. *Cut-and-paste* the template contents into a new heroes.component.html file. - 1. *Cut-and-paste* the styles contents into a new heroes.component.css file. - 1. *Set* the component metadata's `templateUrl` and `styleUrls` properties to refer to both files. + First, move the template contents from `heroes.component.ts` + into a new heroes.component.html file. + Don't copy the backticks. As for `heroes.component.ts`, you'll + come back to it in a minute. Next, move the + styles contents into a new heroes.component.css file. -.l-sub-section - :marked - The `styleUrls` property is !{_an} !{_array} of style file names (with paths). - You could list multiple style files from different locations if you needed them. + The two new files should look like this: + ++makeTabs( + `toh-5/ts/src/app/heroes.component.html, toh-5/ts/src/app/heroes.component.css`, + null, + `src/app/heroes.component.html, src/app/heroes.component.css`) + +:marked + Now, back in the component metadata for `heroes.component.ts`, + delete `template` and `styles`, replacing them with + `templateUrl` and `styleUrls` respectively. + Set their properties to refer to the new files. block heroes-component-cleanup //- Only relevant for Dart. +makeExcerpt('src/app/heroes.component.ts (revised metadata)', 'metadata') +.l-sub-section + :marked + The `styleUrls` property is !{_an} !{_array} of style file names (with paths). + You could list multiple style files from different locations if you needed them. + :marked ### Update the _HeroesComponent_ class The `HeroesComponent` navigates to the `HeroesDetailComponent` in response to a button click. - The button's click event is bound to a `gotoDetail` method that navigates _imperatively_ + The button's click event is bound to a `gotoDetail()` method that navigates _imperatively_ by telling the router where to go. This approach requires the following changes to the component class: 1. Import the `router` from the Angular router library. - 1. Inject the `router` in the constructor (along with the `HeroService`). - 1. Implement `gotoDetail` by calling the `router.navigate` method. + 1. Inject the `router` in the constructor, along with the `HeroService`. + 1. Implement `gotoDetail()` by calling the `router.navigate()` method. +makeExcerpt('src/app/heroes.component.ts', 'gotoDetail') :marked Note that you're passing a two-element *link parameters !{_array}*—a path and the route parameter—to - the `router.navigate` method, just as you did in the `[routerLink]` binding + the `router.navigate()` method, just as you did in the `[routerLink]` binding back in the `DashboardComponent`. Here's the revised `HeroesComponent` class: @@ -788,7 +799,7 @@ block heroes-component-cleanup The dashboard heroes should display in a row of rectangles. You've received around 60 lines of CSS for this purpose, including some simple media queries for responsive design. - Adding the CSS to the component `styles` metadata + As you now know, adding the CSS to the component `styles` metadata would obscure the component logic. Instead, edit the CSS in a separate `*.css` file. @@ -805,7 +816,7 @@ block heroes-component-cleanup Add a hero-detail.component.css to the `!{_appDir}` folder and refer to that file inside the `styleUrls` !{_array} as you did for `DashboardComponent`. - Also, in hero-detail.component.ts, remove the `hero` property `@Input` !{_decorator} + Also, in `hero-detail.component.ts`, remove the `hero` property `@Input` !{_decorator} and its import. Here's the content for the component CSS files. diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index 74b741150d..b0e6ca5c62 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -59,7 +59,7 @@ block http-library block http-providers :marked The app will depend on the Angular `http` service, which itself depends on other supporting services. - The `HttpModule` from `@angular/http` library holds providers for a complete set of HTTP services. + The `HttpModule` from the `@angular/http` library holds providers for a complete set of HTTP services. To allow access to these services from anywhere in the app, add `HttpModule` to the `imports` list of the `AppModule`. @@ -67,7 +67,7 @@ block http-providers +makeExample('src/app/app.module.ts', 'v1','src/app/app.module.ts (v1)') :marked - Notice that you supply `!{_HttpModule}` as part of the *imports* !{_array} in root NgModule `AppModule`. + Notice that you also supply `!{_HttpModule}` as part of the *imports* !{_array} in root NgModule `AppModule`. .l-main-section :marked @@ -97,13 +97,13 @@ block backend +makeExcerpt(_appModuleTsVsMainTs, 'in-mem-web-api', '') :marked - The `forRoot` configuration method takes an `InMemoryDataService` class + The `forRoot()` configuration method takes an `InMemoryDataService` class that primes the in-memory database. Add the file `in-memory-data.service.ts` in `!{_appDir}` with the following content: +makeExample('src/app/in-memory-data.service.ts', 'init')(format='.') :marked - This file replaces the #[code #[+adjExPath('mock-heroes.ts')]], which is now safe to delete. + This file replaces `mock-heroes.ts`, which is now safe to delete. block dont-be-distracted-by-backend-subst .alert.is-helpful @@ -125,7 +125,7 @@ block dont-be-distracted-by-backend-subst +makeExcerpt('toh-4/ts/src/app/hero.service.ts (old getHeroes)', 'get-heroes') :marked - This was implementated in anticipation of ultimately + This was implemented in anticipation of ultimately fetching heroes with an HTTP client, which must be an asynchronous operation. Now convert `getHeroes()` to use HTTP. @@ -171,7 +171,7 @@ block get-heroes-details :marked ### Extracting the data in the *then* callback - In the *Promise*'s `then` callback, you call the `json` method of the HTTP `Response` to extract the + In the *Promise*'s `then()` callback, you call the `json` method of the HTTP `Response` to extract the data within the response. +makeExcerpt('src/app/hero.service.ts', 'to-data', '') @@ -269,18 +269,19 @@ block get-heroes-details ### Add a hero service _update_ method The overall structure of the `update` method is similar to that of - `getHeroes`, but it uses an HTTP *put* to persist server-side changes. + `getHeroes`, but it uses an HTTP `put()` to persist server-side changes. +makeExcerpt('src/app/hero.service.ts', 'update') :marked - To identify which hero the server should update, the hero id is encoded in - the URL. The `put` body is the JSON string encoding of the hero, obtained by + To identify which hero the server should update, the hero `id` is encoded in + the URL. The `put()` body is the JSON string encoding of the hero, obtained by calling `!{_JSON_stringify}`. The body content type (`application/json`) is identified in the request header. - Refresh the browser, change a hero name, save your change, and click the browser `Back` button. Changes should now persist. + Refresh the browser, change a hero name, save your change, + and click the browser Back button. Changes should now persist. .l-main-section :marked @@ -327,12 +328,12 @@ block get-heroes-details +makeExcerpt('src/app/heroes.component.html', 'li-element') :marked - In addition to calling the component's `delete` method, the delete-button - click-handling code stops the propagation of the click event—you + In addition to calling the component's `delete()` method, the delete button's + click handler code stops the propagation of the click event—you don't want the `
  • ` click handler to be triggered because doing so would select the hero that the user will delete. - The logic of the `delete` handler is a bit trickier: + The logic of the `delete()` handler is a bit trickier: +makeExcerpt('src/app/heroes.component.ts', 'delete') @@ -348,9 +349,9 @@ block get-heroes-details +makeExcerpt('src/app/heroes.component.css', 'additions') :marked - ### Hero service `delete` method + ### Hero service `delete()` method - Add the hero service's `delete` method, which uses the _delete_ HTTP method to remove the hero from the server: + Add the hero service's `delete()` method, which uses the `delete()` HTTP method to remove the hero from the server: +makeExcerpt('src/app/hero.service.ts', 'delete') @@ -369,26 +370,26 @@ block observables-section-intro This section shows you how, when, and why to return the `Observable` directly. ### Background - An *observable* is a stream of events that you can process with array-like operators. + An *Observable* is a stream of events that you can process with array-like operators. Angular core has basic support for observables. Developers augment that support with operators and extensions from the RxJS library. You'll see how shortly. - Recall that the `HeroService` chained the `toPromise` operator to the `Observable` result of `http.get`. + Recall that the `HeroService` chained the `toPromise` operator to the `Observable` result of `http.get()`. That operator converted the `Observable` into a `Promise` and you passed that promise back to the caller. - Converting to a promise is often a good choice. You typically ask `http.get` to fetch a single chunk of data. + Converting to a Promise is often a good choice. You typically ask `http.get()` to fetch a single chunk of data. When you receive the data, you're done. - The calling component can easily consume a single result in the form of a promise. + The calling component can easily consume a single result in the form of a Promise. :marked But requests aren't always done only once. You may start one request, cancel it, and make a different request before the server has responded to the first request. - A *request-cancel-new-request* sequence is difficult to implement with *!{_Promise}s*, but - easy with *!{_Observable}s*. + A *request-cancel-new-request* sequence is difficult to implement with *!{Promise}s*, but + easy with *!{Observable}s*. ### Add the ability to search by name You're going to add a *hero search* feature to the Tour of Heroes. @@ -402,13 +403,13 @@ block observables-section-intro The `!{_priv}http.get()` call in `HeroSearchService` is similar to the one in the `HeroService`, although the URL now has a query string. - More importantly, you no longer call `toPromise`. - Instead you return the *observable* from the the `htttp.get`, - after chaining it to another RxJS operator, map, + More importantly, you no longer call `toPromise()`. + Instead you return the *Observable* from the the `htttp.get()`, + after chaining it to another RxJS operator, map(), to extract heroes from the response data. RxJS operator chaining makes response processing easy and readable. - See the [discuss below about operators](#rxjs-imports). + See the [discussion below about operators](#rxjs-imports). :marked ### HeroSearchComponent @@ -422,7 +423,8 @@ block observables-section-intro Also, add styles for the new component. +makeExample('src/app/hero-search.component.css') :marked - As the user types in the search box, a *keyup* event binding calls the component's `search` method with the new search box value. + As the user types in the search box, a *keyup* event binding calls the component's `search()` + method with the new search box value. As expected, the `*ngFor` repeats hero objects from the component's `heroes` property. @@ -446,7 +448,7 @@ block search-criteria-intro A `Subject` is a producer of an _observable_ event stream; `searchTerms` produces an `Observable` of strings, the filter criteria for the name search. - Each call to `search` puts a new string into this subject's _observable_ stream by calling `next`. + Each call to `search()` puts a new string into this subject's _observable_ stream by calling `next()`. :marked @@ -470,25 +472,25 @@ block observable-transformers * `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds before passing along the latest string. You'll never make requests more frequently than 300ms. * `distinctUntilChanged` ensures that a request is sent only if the filter text changed. - * `switchMap` calls the search service for each search term that makes it through `debounce` and `distinctUntilChanged`. + * `switchMap()` calls the search service for each search term that makes it through `debounce` and `distinctUntilChanged`. It cancels and discards previous search observables, returning only the latest search service observable. .l-sub-section :marked With the [switchMap operator](http://www.learnrxjs.io/operators/transformation/switchmap.html) - (formerly known as "flatMapLatest"), - every qualifying key event can trigger an `http` method call. + (formerly known as `flatMapLatest`), + every qualifying key event can trigger an `http()` method call. Even with a 300ms pause between requests, you could have multiple HTTP requests in flight and they may not return in the order sent. - `switchMap` preserves the original request order while returning + `switchMap()` preserves the original request order while returning only the observable from the most recent `http` method call. Results from prior calls are canceled and discarded. - If the search text is empty, the `http` method call is also short circuited + If the search text is empty, the `http()` method call is also short circuited and an observable containing an empty array is returned. - Note that until the service supports that feature, _canceling_ the `HeroSearchService` observable + Note that until the service supports that feature, _canceling_ the `HeroSearchService` Observable doesn't actually abort a pending HTTP request. For now, unwanted results are discarded. :marked @@ -589,7 +591,7 @@ block filetree You're at the end of your journey, and you've accomplished a lot. - You added the necessary dependencies to use HTTP in the app. - You refactored `HeroService` to load heroes from a web API. - - You extended `HeroService` to support post, put, and delete methods. + - You extended `HeroService` to support `post()`, `put()`, and `delete()` methods. - You updated the components to allow adding, editing, and deleting of heroes. - You configured an in-memory web API. - You learned how to use !{_Observable}s.