{ "id": "tutorial/toh-pt5", "title": "Add navigation with routing", "contents": "\n\n\n
\n mode_edit\n
\n\n\n
\n

Add navigation with routinglink

\n

There are new requirements for the Tour of Heroes app:

\n\n
\n

For the sample application that this page describes, see the .

\n
\n

When you’re done, users will be able to navigate the application like this:

\n
\n \"View\n
\n

Add the AppRoutingModulelink

\n

In Angular, the best practice is to load and configure the router in a separate, top-level module\nthat is dedicated to routing and imported by the root AppModule.

\n

By convention, the module class name is AppRoutingModule and it belongs in the app-routing.module.ts in the src/app folder.

\n

Use the CLI to generate it.

\n\n ng generate module app-routing --flat --module=app\n\n
\n

--flat puts the file in src/app instead of its own folder.
\n--module=app tells the CLI to register it in the imports array of the AppModule.

\n
\n

The generated file looks like this:

\n\nimport { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\n@NgModule({\n imports: [\n CommonModule\n ],\n declarations: []\n})\nexport class AppRoutingModule { }\n\n\n\n

Replace it with the following:

\n\nimport { NgModule } from '@angular/core';\nimport { RouterModule, Routes } from '@angular/router';\nimport { HeroesComponent } from './heroes/heroes.component';\n\nconst routes: Routes = [\n { path: 'heroes', component: HeroesComponent }\n];\n\n@NgModule({\n imports: [RouterModule.forRoot(routes)],\n exports: [RouterModule]\n})\nexport class AppRoutingModule { }\n\n\n\n

First, the app-routing.module.ts file imports RouterModule and Routes so the application can have routing functionality. The next import, HeroesComponent, will give the Router somewhere to go once you configure the routes.

\n

Notice that the CommonModule references and declarations array are unnecessary, so are no\nlonger part of AppRoutingModule. The following sections explain the rest of the AppRoutingModule in more detail.

\n

Routeslink

\n

The next part of the file is where you configure your routes.\nRoutes tell the Router which view to display when a user clicks a link or\npastes a URL into the browser address bar.

\n

Since app-routing.module.ts already imports HeroesComponent, you can use it in the routes array:

\n\n\nconst routes: Routes = [\n { path: 'heroes', component: HeroesComponent }\n];\n\n\n

A typical Angular Route has two properties:

\n\n

This tells the router to match that URL to path: 'heroes'\nand display the HeroesComponent when the URL is something like localhost:4200/heroes.

\n

RouterModule.forRoot()link

\n

The @NgModule metadata initializes the router and starts it listening for browser location changes.

\n

The following line adds the RouterModule to the AppRoutingModule imports array and\nconfigures it with the routes in one step by calling\nRouterModule.forRoot():

\n\nimports: [ RouterModule.forRoot(routes) ],\n\n\n
\n

The method is called forRoot() because you configure the router at the application's root level.\nThe forRoot() method supplies the service providers and directives needed for routing,\nand performs the initial navigation based on the current browser URL.

\n
\n

Next, AppRoutingModule exports RouterModule so it will be available throughout the app.

\n\nexports: [ RouterModule ]\n\n\n

Add RouterOutletlink

\n

Open the AppComponent template and replace the <app-heroes> element with a <router-outlet> element.

\n\n<h1>{{title}}</h1>\n<router-outlet></router-outlet>\n<app-messages></app-messages>\n\n\n

The AppComponent template no longer needs <app-heroes> because the application will only display the HeroesComponent when the user navigates to it.

\n

The <router-outlet> tells the router where to display routed views.

\n
\n

The RouterOutlet is one of the router directives that became available to the AppComponent\nbecause AppModule imports AppRoutingModule which exported RouterModule. The ng generate command you ran at the start of this tutorial added this import because of the --module=app flag. If you manually created app-routing.module.ts or used a tool other than the CLI to do so, you'll need to import AppRoutingModule into app.module.ts and add it to the imports array of the NgModule.

\n
\n

Try itlink

\n

You should still be running with this CLI command.

\n\n ng serve\n\n

The browser should refresh and display the application title but not the list of heroes.

\n

Look at the browser's address bar.\nThe URL ends in /.\nThe route path to HeroesComponent is /heroes.

\n

Append /heroes to the URL in the browser address bar.\nYou should see the familiar heroes master/detail view.

\n\n\n

Ideally, users should be able to click a link to navigate rather\nthan pasting a route URL into the address bar.

\n

Add a <nav> element and, within that, an anchor element that, when clicked,\ntriggers navigation to the HeroesComponent.\nThe revised AppComponent template looks like this:

\n\n<h1>{{title}}</h1>\n<nav>\n <a routerLink=\"/heroes\">Heroes</a>\n</nav>\n<router-outlet></router-outlet>\n<app-messages></app-messages>\n\n\n

A routerLink attribute is set to \"/heroes\",\nthe string that the router matches to the route to HeroesComponent.\nThe routerLink is the selector for the RouterLink directive\nthat turns user clicks into router navigations.\nIt's another of the public directives in the RouterModule.

\n

The browser refreshes and displays the application title and heroes link,\nbut not the heroes list.

\n

Click the link.\nThe address bar updates to /heroes and the list of heroes appears.

\n
\n

Make this and future navigation links look better by adding private CSS styles to app.component.css\nas listed in the final code review below.

\n
\n

Add a dashboard viewlink

\n

Routing makes more sense when there are multiple views.\nSo far there's only the heroes view.

\n

Add a DashboardComponent using the CLI:

\n\n ng generate component dashboard\n\n

The CLI generates the files for the DashboardComponent and declares it in AppModule.

\n

Replace the default file content in these three files as follows:

\n\n \n<h2>Top Heroes</h2>\n<div class=\"heroes-menu\">\n <a *ngFor=\"let hero of heroes\">\n {{hero.name}}\n </a>\n</div>\n\n\n\n\n \nimport { Component, OnInit } from '@angular/core';\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@Component({\n selector: 'app-dashboard',\n templateUrl: './dashboard.component.html',\n styleUrls: [ './dashboard.component.css' ]\n})\nexport class DashboardComponent implements OnInit {\n heroes: Hero[] = [];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes.slice(1, 5));\n }\n}\n\n\n\n\n \n/* DashboardComponent's private CSS styles */\n\nh2 {\n text-align: center;\n}\n\n.heroes-menu {\n padding: 0;\n margin: auto;\n max-width: 1000px;\n\n /* flexbox */\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-around;\n align-content: flex-start;\n align-items: flex-start;\n}\n\na {\n background-color: #3f525c;\n border-radius: 2px;\n padding: 1rem;\n font-size: 1.2rem;\n text-decoration: none;\n display: inline-block;\n color: #fff;\n text-align: center;\n width: 100%;\n min-width: 70px;\n margin: .5rem auto;\n box-sizing: border-box;\n\n /* flexbox */\n order: 0;\n flex: 0 1 auto;\n align-self: auto;\n}\n\n@media (min-width: 600px) {\n a {\n width: 18%;\n box-sizing: content-box;\n }\n}\n\na:hover {\n background-color: #000;\n}\n\n\n\n\n

The template presents a grid of hero name links.

\n\n

The class is similar to the HeroesComponent class.

\n\n

This getHeroes() returns the sliced list of heroes at positions 1 and 5, returning only four of the Top Heroes (2nd, 3rd, 4th, and 5th).

\n\ngetHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes.slice(1, 5));\n}\n\n\n

Add the dashboard routelink

\n

To navigate to the dashboard, the router needs an appropriate route.

\n

Import the DashboardComponent in the app-routing-module.ts file.

\n\nimport { DashboardComponent } from './dashboard/dashboard.component';\n\n\n

Add a route to the routes array that matches a path to the DashboardComponent.

\n\n{ path: 'dashboard', component: DashboardComponent },\n\n\n

Add a default routelink

\n

When the application starts, the browser's address bar points to the web site's root.\nThat doesn't match any existing route so the router doesn't navigate anywhere.\nThe space below the <router-outlet> is blank.

\n

To make the application navigate to the dashboard automatically, add the following\nroute to the routes array.

\n\n{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n\n\n

This route redirects a URL that fully matches the empty path to the route whose path is '/dashboard'.

\n

After the browser refreshes, the router loads the DashboardComponent\nand the browser address bar shows the /dashboard URL.

\n\n

The user should be able to navigate back and forth between the\nDashboardComponent and the HeroesComponent by clicking links in the\nnavigation area near the top of the page.

\n

Add a dashboard navigation link to the AppComponent shell template, just above the Heroes link.

\n\n<h1>{{title}}</h1>\n<nav>\n <a routerLink=\"/dashboard\">Dashboard</a>\n <a routerLink=\"/heroes\">Heroes</a>\n</nav>\n<router-outlet></router-outlet>\n<app-messages></app-messages>\n\n\n

After the browser refreshes you can navigate freely between the two views by clicking the links.

\n\n

Navigating to hero detailslink

\n

The HeroDetailsComponent displays details of a selected hero.\nAt the moment the HeroDetailsComponent is only visible at the bottom of the HeroesComponent

\n

The user should be able to get to these details in three ways.

\n
    \n
  1. By clicking a hero in the dashboard.
  2. \n
  3. By clicking a hero in the heroes list.
  4. \n
  5. By pasting a \"deep link\" URL into the browser address bar that identifies the hero to display.
  6. \n
\n

In this section, you'll enable navigation to the HeroDetailsComponent\nand liberate it from the HeroesComponent.

\n

Delete hero details from HeroesComponentlink

\n

When the user clicks a hero item in the HeroesComponent,\nthe application should navigate to the HeroDetailComponent,\nreplacing the heroes list view with the hero detail view.\nThe heroes list view should no longer show hero details as it does now.

\n

Open the HeroesComponent template (heroes/heroes.component.html) and\ndelete the <app-hero-detail> element from the bottom.

\n

Clicking a hero item now does nothing.\nYou'll fix that shortly after you enable routing to the HeroDetailComponent.

\n

Add a hero detail routelink

\n

A URL like ~/detail/11 would be a good URL for navigating to the Hero Detail view of the hero whose id is 11.

\n

Open app-routing.module.ts and import HeroDetailComponent.

\n\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\n\n

Then add a parameterized route to the routes array that matches the path pattern to the hero detail view.

\n\n{ path: 'detail/:id', component: HeroDetailComponent },\n\n\n

The colon (:) in the path indicates that :id is a placeholder for a specific hero id.

\n

At this point, all application routes are in place.

\n\nconst routes: Routes = [\n { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n { path: 'dashboard', component: DashboardComponent },\n { path: 'detail/:id', component: HeroDetailComponent },\n { path: 'heroes', component: HeroesComponent }\n];\n\n\n

DashboardComponent hero linkslink

\n

The DashboardComponent hero links do nothing at the moment.

\n

Now that the router has a route to HeroDetailComponent,\nfix the dashboard hero links to navigate via the parameterized dashboard route.

\n\n<a *ngFor=\"let hero of heroes\"\n routerLink=\"/detail/{{hero.id}}\">\n {{hero.name}}\n</a>\n\n\n

You're using Angular interpolation binding within the *ngFor repeater\nto insert the current iteration's hero.id into each\nrouterLink.

\n\n

HeroesComponent hero linkslink

\n

The hero items in the HeroesComponent are <li> elements whose click events\nare bound to the component's onSelect() method.

\n\n<ul class=\"heroes\">\n <li *ngFor=\"let hero of heroes\"\n [class.selected]=\"hero === selectedHero\"\n (click)=\"onSelect(hero)\">\n <span class=\"badge\">{{hero.id}}</span> {{hero.name}}\n </li>\n</ul>\n\n\n

Strip the <li> back to just its *ngFor,\nwrap the badge and name in an anchor element (<a>),\nand add a routerLink attribute to the anchor that\nis the same as in the dashboard template

\n\n<ul class=\"heroes\">\n <li *ngFor=\"let hero of heroes\">\n <a routerLink=\"/detail/{{hero.id}}\">\n <span class=\"badge\">{{hero.id}}</span> {{hero.name}}\n </a>\n </li>\n</ul>\n\n\n

You'll have to fix the private stylesheet (heroes.component.css) to make\nthe list look as it did before.\nRevised styles are in the final code review at the bottom of this guide.

\n

Remove dead code (optional)link

\n

While the HeroesComponent class still works,\nthe onSelect() method and selectedHero property are no longer used.

\n

It's nice to tidy up and you'll be grateful to yourself later.\nHere's the class after pruning away the dead code.

\n\nexport class HeroesComponent implements OnInit {\n heroes: Hero[];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes);\n }\n}\n\n\n

Routable HeroDetailComponentlink

\n

Previously, the parent HeroesComponent set the HeroDetailComponent.hero\nproperty and the HeroDetailComponent displayed the hero.

\n

HeroesComponent doesn't do that anymore.\nNow the router creates the HeroDetailComponent in response to a URL such as ~/detail/11.

\n

The HeroDetailComponent needs a new way to obtain the hero-to-display.\nThis section explains the following:

\n\n

Add the following imports:

\n\nimport { ActivatedRoute } from '@angular/router';\nimport { Location } from '@angular/common';\n\nimport { HeroService } from '../hero.service';\n\n\n\n

Inject the ActivatedRoute, HeroService, and Location services\ninto the constructor, saving their values in private fields:

\n\nconstructor(\n private route: ActivatedRoute,\n private heroService: HeroService,\n private location: Location\n) {}\n\n\n

The ActivatedRoute holds information about the route to this instance of the HeroDetailComponent.\nThis component is interested in the route's parameters extracted from the URL.\nThe \"id\" parameter is the id of the hero to display.

\n

The HeroService gets hero data from the remote server\nand this component will use it to get the hero-to-display.

\n

The location is an Angular service for interacting with the browser.\nYou'll use it later to navigate back to the view that navigated here.

\n

Extract the id route parameterlink

\n

In the ngOnInit() lifecycle hook\ncall getHero() and define it as follows.

\n\nngOnInit(): void {\n this.getHero();\n}\n\ngetHero(): void {\n const id = +this.route.snapshot.paramMap.get('id');\n this.heroService.getHero(id)\n .subscribe(hero => this.hero = hero);\n}\n\n\n

The route.snapshot is a static image of the route information shortly after the component was created.

\n

The paramMap is a dictionary of route parameter values extracted from the URL.\nThe \"id\" key returns the id of the hero to fetch.

\n

Route parameters are always strings.\nThe JavaScript (+) operator converts the string to a number,\nwhich is what a hero id should be.

\n

The browser refreshes and the application crashes with a compiler error.\nHeroService doesn't have a getHero() method.\nAdd it now.

\n

Add HeroService.getHero()link

\n

Open HeroService and add the following getHero() method with the id after the getHeroes() method:

\n\ngetHero(id: number): Observable<Hero> {\n // For now, assume that a hero with the specified `id` always exists.\n // Error handling will be added in the next step of the tutorial.\n const hero = HEROES.find(h => h.id === id) as Hero;\n this.messageService.add(`HeroService: fetched hero id=${id}`);\n return of(hero);\n}\n\n\n
\n

Note the backticks ( ` ) that define a JavaScript\ntemplate literal for embedding the id.

\n
\n

Like getHeroes(),\ngetHero() has an asynchronous signature.\nIt returns a mock hero as an Observable, using the RxJS of() function.

\n

You'll be able to re-implement getHero() as a real Http request\nwithout having to change the HeroDetailComponent that calls it.

\n

Try itlink

\n

The browser refreshes and the application is working again.\nYou can click a hero in the dashboard or in the heroes list and navigate to that hero's detail view.

\n

If you paste localhost:4200/detail/11 in the browser address bar,\nthe router navigates to the detail view for the hero with id: 11, \"Dr Nice\".

\n\n

Find the way backlink

\n

By clicking the browser's back button,\nyou can go back to the hero list or dashboard view,\ndepending upon which sent you to the detail view.

\n

It would be nice to have a button on the HeroDetail view that can do that.

\n

Add a go back button to the bottom of the component template and bind it\nto the component's goBack() method.

\n\n<button (click)=\"goBack()\">go back</button>\n\n\n

Add a goBack() method to the component class that navigates backward one step\nin the browser's history stack\nusing the Location service that you injected previously.

\n\ngoBack(): void {\n this.location.back();\n}\n\n\n

Refresh the browser and start clicking.\nUsers can navigate around the app, from the dashboard to hero details and back,\nfrom heroes list to the mini detail to the hero details and back to the heroes again.

\n

Final code reviewlink

\n

Here are the code files discussed on this page.

\n\n\n

AppRoutingModule, AppModule, and HeroServicelink

\n\n \nimport { NgModule } from '@angular/core';\nimport { RouterModule, Routes } from '@angular/router';\n\nimport { DashboardComponent } from './dashboard/dashboard.component';\nimport { HeroesComponent } from './heroes/heroes.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nconst routes: Routes = [\n { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n { path: 'dashboard', component: DashboardComponent },\n { path: 'detail/:id', component: HeroDetailComponent },\n { path: 'heroes', component: HeroesComponent }\n];\n\n@NgModule({\n imports: [ RouterModule.forRoot(routes) ],\n exports: [ RouterModule ]\n})\nexport class AppRoutingModule {}\n\n\n \nimport { NgModule } from '@angular/core';\nimport { BrowserModule } from '@angular/platform-browser';\nimport { FormsModule } from '@angular/forms';\n\nimport { AppComponent } from './app.component';\nimport { DashboardComponent } from './dashboard/dashboard.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\nimport { HeroesComponent } from './heroes/heroes.component';\nimport { MessagesComponent } from './messages/messages.component';\n\nimport { AppRoutingModule } from './app-routing.module';\n\n@NgModule({\n imports: [\n BrowserModule,\n FormsModule,\n AppRoutingModule\n ],\n declarations: [\n AppComponent,\n DashboardComponent,\n HeroesComponent,\n HeroDetailComponent,\n MessagesComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n\n\n \nimport { Injectable } from '@angular/core';\n\nimport { Observable, of } from 'rxjs';\n\nimport { Hero } from './hero';\nimport { HEROES } from './mock-heroes';\nimport { MessageService } from './message.service';\n\n@Injectable({ providedIn: 'root' })\nexport class HeroService {\n\n constructor(private messageService: MessageService) { }\n\n getHeroes(): Observable<Hero[]> {\n const heroes = of(HEROES);\n this.messageService.add('HeroService: fetched heroes');\n return heroes;\n }\n\n getHero(id: number): Observable<Hero> {\n // For now, assume that a hero with the specified `id` always exists.\n // Error handling will be added in the next step of the tutorial.\n const hero = HEROES.find(h => h.id === id) as Hero;\n this.messageService.add(`HeroService: fetched hero id=${id}`);\n return of(hero);\n }\n}\n\n\n\n\n\n

AppComponentlink

\n\n \n<h1>{{title}}</h1>\n<nav>\n <a routerLink=\"/dashboard\">Dashboard</a>\n <a routerLink=\"/heroes\">Heroes</a>\n</nav>\n<router-outlet></router-outlet>\n<app-messages></app-messages>\n\n\n\n \n/* AppComponent's private CSS styles */\nh1 {\n margin-bottom: 0;\n}\nnav a {\n padding: 1rem;\n text-decoration: none;\n margin-top: 10px;\n display: inline-block;\n background-color: #e8e8e8;\n color: #3d3d3d;\n border-radius: 4px;\n}\n\nnav a:hover {\n color: white;\n background-color: #42545C;\n}\nnav a.active {\n background-color: black;\n}\n\n\n\n\n\n

DashboardComponentlink

\n\n \n<h2>Top Heroes</h2>\n<div class=\"heroes-menu\">\n <a *ngFor=\"let hero of heroes\"\n routerLink=\"/detail/{{hero.id}}\">\n {{hero.name}}\n </a>\n</div>\n\n\n\n\n \nimport { Component, OnInit } from '@angular/core';\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@Component({\n selector: 'app-dashboard',\n templateUrl: './dashboard.component.html',\n styleUrls: [ './dashboard.component.css' ]\n})\nexport class DashboardComponent implements OnInit {\n heroes: Hero[] = [];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes.slice(1, 5));\n }\n}\n\n\n\n\n \n/* DashboardComponent's private CSS styles */\n\nh2 {\n text-align: center;\n}\n\n.heroes-menu {\n padding: 0;\n margin: auto;\n max-width: 1000px;\n\n /* flexbox */\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-around;\n align-content: flex-start;\n align-items: flex-start;\n}\n\na {\n background-color: #3f525c;\n border-radius: 2px;\n padding: 1rem;\n font-size: 1.2rem;\n text-decoration: none;\n display: inline-block;\n color: #fff;\n text-align: center;\n width: 100%;\n min-width: 70px;\n margin: .5rem auto;\n box-sizing: border-box;\n\n /* flexbox */\n order: 0;\n flex: 0 1 auto;\n align-self: auto;\n}\n\n@media (min-width: 600px) {\n a {\n width: 18%;\n box-sizing: content-box;\n }\n}\n\na:hover {\n background-color: #000;\n}\n\n\n\n\n\n

HeroesComponentlink

\n\n \n<h2>My Heroes</h2>\n<ul class=\"heroes\">\n <li *ngFor=\"let hero of heroes\">\n <a routerLink=\"/detail/{{hero.id}}\">\n <span class=\"badge\">{{hero.id}}</span> {{hero.name}}\n </a>\n </li>\n</ul>\n\n\n\n\n \nimport { Component, OnInit } from '@angular/core';\n\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@Component({\n selector: 'app-heroes',\n templateUrl: './heroes.component.html',\n styleUrls: ['./heroes.component.css']\n})\nexport class HeroesComponent implements OnInit {\n heroes: Hero[];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes);\n }\n}\n\n\n\n\n \n/* HeroesComponent's private CSS styles */\n.heroes {\n margin: 0 0 2em 0;\n list-style-type: none;\n padding: 0;\n width: 15em;\n}\n.heroes li {\n position: relative;\n cursor: pointer;\n}\n\n.heroes li:hover {\n left: .1em;\n}\n\n.heroes a {\n color: #333;\n text-decoration: none;\n background-color: #EEE;\n margin: .5em;\n padding: .3em 0;\n height: 1.6em;\n border-radius: 4px;\n display: block;\n width: 100%;\n}\n\n.heroes a:hover {\n color: #2c3a41;\n background-color: #e6e6e6;\n}\n\n.heroes a:active {\n background-color: #525252;\n color: #fafafa;\n}\n\n.heroes .badge {\n display: inline-block;\n font-size: small;\n color: white;\n padding: 0.8em 0.7em 0 0.7em;\n background-color:#405061;\n line-height: 1em;\n position: relative;\n left: -1px;\n top: -4px;\n height: 1.8em;\n min-width: 16px;\n text-align: right;\n margin-right: .8em;\n border-radius: 4px 0 0 4px;\n}\n\n\n\n\n\n

HeroDetailComponentlink

\n\n \n<div *ngIf=\"hero\">\n <h2>{{hero.name | uppercase}} Details</h2>\n <div><span>id: </span>{{hero.id}}</div>\n <div>\n <label for=\"hero-name\">Hero name: </label>\n <input id=\"hero-name\" [(ngModel)]=\"hero.name\" placeholder=\"Hero name\"/>\n </div>\n <button (click)=\"goBack()\">go back</button>\n</div>\n\n\n\n\n \nimport { Component, OnInit } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport { Location } from '@angular/common';\n\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@Component({\n selector: 'app-hero-detail',\n templateUrl: './hero-detail.component.html',\n styleUrls: [ './hero-detail.component.css' ]\n})\nexport class HeroDetailComponent implements OnInit {\n hero: Hero;\n\n constructor(\n private route: ActivatedRoute,\n private heroService: HeroService,\n private location: Location\n ) {}\n\n ngOnInit(): void {\n this.getHero();\n }\n\n getHero(): void {\n const id = +this.route.snapshot.paramMap.get('id');\n this.heroService.getHero(id)\n .subscribe(hero => this.hero = hero);\n }\n\n goBack(): void {\n this.location.back();\n }\n}\n\n\n\n\n \n/* HeroDetailComponent's private CSS styles */\nlabel {\n color: #435960;\n font-weight: bold;\n}\ninput {\n font-size: 1em;\n padding: .5rem;\n}\nbutton {\n margin-top: 20px;\n background-color: #eee;\n padding: 1rem;\n border-radius: 4px;\n font-size: 1rem;\n}\nbutton:hover {\n background-color: #cfd8dc;\n}\nbutton:disabled {\n background-color: #eee;\n color: #ccc;\n cursor: auto;\n}\n\n\n\n\n

Summarylink

\n\n\n \n
\n\n\n" }