Skip to content

Angular Tutorial: Tour of Heroes

Michael O'Sullivan edited this page Nov 24, 2017 · 6 revisions

Angular Tutorial: Tour of Heroes

Angular has provided an excellent tutorial application to help you get up and running quickly: the Tour Of Heroes application. Divided into several parts, it covers some of the core functionality of the Angular framework. Spending some time following it is highly recommend.

Find the tutorial at https://angular.io/tutorial - It is divided up into 8 parts, which you will see on the left-hand side of the page.

There were a few typographical errors and unclear items that I found while running through the tutorial, and to help you along, these are now documented below. Make sure you look at the sections below for the corresponding part you are working on, so as to not run into anything that will trip you up!

Note: To install the Angular CLI tool, you first install Node.js, and then running the following command in a command line/terminal window:

npm install -g @angular/cli

3. The Hero Editor

Add a hero property

This subsection asks you to: Add a hero property to the HeroesComponent for a hero named "Windstorm."

There are several places in the tutorial that ask you to add a property to a component. These properties should appear inside the class, that you find in the component.ts file in question, near the top. In this example, it should look like this

heroes.component.ts (hero property):

export class HeroesComponent implements OnInit {

    hero = 'Windstorm';

6. Services

Provide the HeroService

In this subsection, you are asked to: Open the AppModule class, import the HeroService, and add it to the @NgModule.providers array.

src/app/app.module.ts (providers):

providers: [ HeroService, MessageService ],

Note, that MessageService is here in the providers list. If you try and run the application at this point, it will crash with an error. This is because you have not yet created the MessageService. Instead, the providers list should simply look like this:

src/app/app.module.ts (providers):

providers: [ HeroService ],

Once you create the MessageService later in the tutorial, come back here and add it to the providers list.

7. Routing

Add routes

In this subsection, you are asked to: Then define an array of routes with a single route to that component.

app-routing.module.ts:

import { HeroesComponent }      from './heroes/heroes.component';

const routes: Routes = [
  { path: 'heroes', component: HeroesComponent }
];

Just note that here, you are defining a constant property called routes. Unlike other properties you have created in the tutorial up until now, a constant cannot be created inside a class - you can see above that it appears right under the list of import statements. You can then use it inside the class.

8. HTTP

Simulate a data server

In this subsection, you are asked to: Import the InMemoryWebApiModule and the InMemoryDataService class, which you will create in a moment.

src/app/app.module.ts (In-memory Web API imports):

import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService }  from './in-memory-data.service';

Add the InMemoryWebApiModule to the @NgModule.imports array— after importing the HttpClient, —while configuring it with the InMemoryDataService.

HttpClientModule,

// The HttpClientInMemoryWebApiModule module intercepts HTTP requests
// and returns simulated server responses.
// Remove it when a real server is ready to receive requests.
HttpClientInMemoryWebApiModule.forRoot(
  InMemoryDataService, { dataEncapsulation: false }
)

I got a little confused here, and tried to import { HttpClient } from '@angular/common/http', but this is not correct, even though it shows no error. You need to import HttpClientModule from @angular/common/http. The imports section of the code should contain these new additional imports as a result of walking through this subsection (leaving out here all the other previous imports from the extract below!):

src/app/app.module.ts:

import { HttpClientModule } from '@angular/common/http'
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService }  from './in-memory-data.service';

Furthermore, when you are done with the above, the @NgModule block should look like this:

@NgModule({
  declarations: [
    AppComponent,
    HeroesComponent,
    HeroDetailComponent,
    MessagesComponent,
    DashboardComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule,
    // The HttpClientInMemoryWebApiModule module intercepts HTTP requests
// and returns simulated server responses.
// Remove it when a real server is ready to receive requests.
    HttpClientInMemoryWebApiModule.forRoot(
      InMemoryDataService, { dataEncapsulation: false })
  ],
  providers: [ HeroService, MessageService],
  bootstrap: [AppComponent]
})

handleError

The big block of code in this subsection (handleError<T>() function/method) should go inside the HeroService class in hero.service.ts.

Chaining RxJS operators

The big block of searchTerms.pipe() code in this subsection, must go inside the HeroSearchComponent class in hero-search.component.ts, specifically inside the ngOnInit() function/method. The class inside this file will look like this:

export class HeroSearchComponent implements OnInit {
  heroes$: Observable<Hero[]>;
  private searchTerms = new Subject<string>();

  constructor(private heroService: HeroService) {}

  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
  }

  ngOnInit(): void {
    this.heroes$ = this.searchTerms.pipe(
      // wait 300ms after each keystroke before considering the term
      debounceTime(300),

      // ignore new term if same as previous term
      distinctUntilChanged(),

      // switch to new search observable each time the term changes
      switchMap((term: string) => this.heroService.searchHeroes(term)),
    );
  }
}