This tutorial lesson demonstrates how to connect the details page to your app.
IMPORTANT: We recommend using your local environment to learn routing.
What you'll learn
At the end of this lesson your application will have support for routing to the details page.
Conceptual preview of routing with route parameters
Each housing location has specific details that should be displayed when a user navigates to the details page for that item. To accomplish this goal, you will need to use route parameters.
Route parameters enable you to include dynamic information as a part of your route URL. To identify which housing location a user has clicked on you will use the id property of the HousingLocation type.
- 
      
      
  UsingrouterLinkfor dynamic navigationIn lesson 10, you added a second route to src/app/routes.tswhich includes a special segment that identifies the route parameter,id:'details/:id'In this case, :idis dynamic and will change based on how the route is requested by the code.- In - src/app/housing-location/housing-location.component.ts, add an anchor tag to the- sectionelement and include the- routerLinkdirective:- Add anchor with a routerLink directive to housing-location.component.ts- import {Component, Input} from '@angular/core';import {CommonModule} from '@angular/common';import {HousingLocation} from '../housinglocation';import {RouterModule} from '@angular/router';@Component({ selector: 'app-housing-location', standalone: true, imports: [CommonModule, RouterModule], template: ` <section class="listing"> <img class="listing-photo" [src]="housingLocation.photo" alt="Exterior photo of {{ housingLocation.name }}" crossorigin /> <h2 class="listing-heading">{{ housingLocation.name }}</h2> <p class="listing-location">{{ housingLocation.city }}, {{ housingLocation.state }}</p> <a [routerLink]="['/details', housingLocation.id]">Learn More</a> </section> `, styleUrls: ['./housing-location.component.css'],})export class HousingLocationComponent { @Input() housingLocation!: HousingLocation;}- The - routerLinkdirective enables Angular's router to create dynamic links in the application. The value assigned to the- routerLinkis an array with two entries: the static portion of the path and the dynamic data.- For the - routerLinkto work in the template, add a file level import of- RouterLinkand- RouterOutletfrom '@angular/router', then update the component- importsarray to include both- RouterLinkand- RouterOutlet.
- At this point you can confirm that the routing is working in your app. In the browser, refresh the home page and click the "Learn More" button for a housing location.  
 
- 
      
      
  Get route parametersIn this step, you will get the route parameter in the DetailsComponent. Currently, the app displaysdetails works!. Next you'll update the code to display theidvalue passed using the route parameters.- In - src/app/details/details.component.tsupdate the template to import the functions, classes and services that you'll need to use in the- DetailsComponent:- Update file level imports- import {Component, inject} from '@angular/core';import {CommonModule} from '@angular/common';import {ActivatedRoute} from '@angular/router';import {HousingService} from '../housing.service';import {HousingLocation} from '../housinglocation';@Component({ selector: 'app-details', standalone: true, imports: [CommonModule], template: ` <article> <img class="listing-photo" [src]="housingLocation?.photo" alt="Exterior photo of {{ housingLocation?.name }}" crossorigin /> <section class="listing-description"> <h2 class="listing-heading">{{ housingLocation?.name }}</h2> <p class="listing-location">{{ housingLocation?.city }}, {{ housingLocation?.state }}</p> </section> <section class="listing-features"> <h2 class="section-heading">About this housing location</h2> <ul> <li>Units available: {{ housingLocation?.availableUnits }}</li> <li>Does this location have wifi: {{ housingLocation?.wifi }}</li> <li>Does this location have laundry: {{ housingLocation?.laundry }}</li> </ul> </section> </article> `, styleUrls: ['./details.component.css'],})export class DetailsComponent { route: ActivatedRoute = inject(ActivatedRoute); housingService = inject(HousingService); housingLocation: HousingLocation | undefined; constructor() { const housingLocationId = Number(this.route.snapshot.params['id']); this.housingLocation = this.housingService.getHousingLocationById(housingLocationId); }}
- Update the - templateproperty of the- @Componentdecorator to display the value- housingLocationId:- template: `<p>details works! {{ housingLocationId }}</p>`,
- Update the body of the - DetailsComponentclass with the following code:- export class DetailsComponent { route: ActivatedRoute = inject(ActivatedRoute); housingLocationId = -1; constructor() { this.housingLocationId = Number(this.route.snapshot.params['id']); } }- This code gives the - DetailsComponentaccess to the- ActivatedRouterouter feature that enables you to have access to the data about the current route. In the- constructor, the code converts the- idparameter acquired from the route from a string to a number.
- Save all changes. 
- In the browser, click on one of the housing location's "Learn More" links and confirm that the numeric value displayed on the page matches the - idproperty for that location in the data.
 
- 
      
      
  Customize theDetailComponentNow that routing is working properly in the application this is a great time to update the template of the DetailsComponentto display the specific data represented by the housing location for the route parameter.To access the data you will add a call to the HousingService.- Update the template code to match the following code: - Update the DetailsComponent template in src/app/details/details.component.ts- import {Component, inject} from '@angular/core';import {CommonModule} from '@angular/common';import {ActivatedRoute} from '@angular/router';import {HousingService} from '../housing.service';import {HousingLocation} from '../housinglocation';@Component({ selector: 'app-details', standalone: true, imports: [CommonModule], template: ` <article> <img class="listing-photo" [src]="housingLocation?.photo" alt="Exterior photo of {{ housingLocation?.name }}" crossorigin /> <section class="listing-description"> <h2 class="listing-heading">{{ housingLocation?.name }}</h2> <p class="listing-location">{{ housingLocation?.city }}, {{ housingLocation?.state }}</p> </section> <section class="listing-features"> <h2 class="section-heading">About this housing location</h2> <ul> <li>Units available: {{ housingLocation?.availableUnits }}</li> <li>Does this location have wifi: {{ housingLocation?.wifi }}</li> <li>Does this location have laundry: {{ housingLocation?.laundry }}</li> </ul> </section> </article> `, styleUrls: ['./details.component.css'],})export class DetailsComponent { route: ActivatedRoute = inject(ActivatedRoute); housingService = inject(HousingService); housingLocation: HousingLocation | undefined; constructor() { const housingLocationId = Number(this.route.snapshot.params['id']); this.housingLocation = this.housingService.getHousingLocationById(housingLocationId); }}- Notice that the - housingLocationproperties are being accessed with the optional chaining operator- ?. This ensures that if the- housingLocationvalue is null or undefined the application doesn't crash.
- Update the body of the - DetailsComponentclass to match the following code:- Update the DetailsComponent class in src/app/details/details.component.ts- import {Component, inject} from '@angular/core';import {CommonModule} from '@angular/common';import {ActivatedRoute} from '@angular/router';import {HousingService} from '../housing.service';import {HousingLocation} from '../housinglocation';@Component({ selector: 'app-details', standalone: true, imports: [CommonModule], template: ` <article> <img class="listing-photo" [src]="housingLocation?.photo" alt="Exterior photo of {{ housingLocation?.name }}" crossorigin /> <section class="listing-description"> <h2 class="listing-heading">{{ housingLocation?.name }}</h2> <p class="listing-location">{{ housingLocation?.city }}, {{ housingLocation?.state }}</p> </section> <section class="listing-features"> <h2 class="section-heading">About this housing location</h2> <ul> <li>Units available: {{ housingLocation?.availableUnits }}</li> <li>Does this location have wifi: {{ housingLocation?.wifi }}</li> <li>Does this location have laundry: {{ housingLocation?.laundry }}</li> </ul> </section> </article> `, styleUrls: ['./details.component.css'],})export class DetailsComponent { route: ActivatedRoute = inject(ActivatedRoute); housingService = inject(HousingService); housingLocation: HousingLocation | undefined; constructor() { const housingLocationId = Number(this.route.snapshot.params['id']); this.housingLocation = this.housingService.getHousingLocationById(housingLocationId); }}- Now the component has the code to display the correct information based on the selected housing location. The - constructornow includes a call to the- HousingServiceto pass the route parameter as an argument to the- getHousingLocationByIdservice function.
- Copy the following styles into the - src/app/details/details.component.cssfile:- Add styles for the DetailsComponent- .listing-photo { height: 600px; width: 50%; object-fit: cover; border-radius: 30px; float: right;}.listing-heading { font-size: 48pt; font-weight: bold; margin-bottom: 15px;}.listing-location::before { content: url('/assets/location-pin.svg') / '';}.listing-location { font-size: 24pt; margin-bottom: 15px;}.listing-features > .section-heading { color: var(--secondary-color); font-size: 24pt; margin-bottom: 15px;}.listing-features { margin-bottom: 20px;}.listing-features li { font-size: 14pt;}li { list-style-type: none;}.listing-apply .section-heading { font-size: 18pt; margin-bottom: 15px;}label, input { display: block;}label { color: var(--secondary-color); font-weight: bold; text-transform: uppercase; font-size: 12pt;}input { font-size: 16pt; margin-bottom: 15px; padding: 10px; width: 400px; border-top: none; border-right: none; border-left: none; border-bottom: solid .3px;}@media (max-width: 1024px) { .listing-photo { width: 100%; height: 400px; }}
- Save your changes. 
- In the browser refresh the page and confirm that when you click on the "Learn More" link for a given housing location the details page displays the correct information based on the data for that selected item.  
 
- 
      
      
  Add navigation to theHomeComponentIn a previous lesson you updated the AppComponenttemplate to include arouterLink. Adding that code updated your app to enable navigation back to theHomeComponentwhenever the logo is clicked.- Confirm that your code matches the following: - Add routerLink to AppComponent- import {Component} from '@angular/core';import {HomeComponent} from './home/home.component';import {RouterLink, RouterOutlet} from '@angular/router';@Component({ selector: 'app-root', standalone: true, imports: [HomeComponent, RouterLink, RouterOutlet], template: ` <main> <a [routerLink]="['/']"> <header class="brand-name"> <img class="brand-logo" src="/assets/logo.svg" alt="logo" aria-hidden="true" /> </header> </a> <section class="content"> <router-outlet></router-outlet> </section> </main> `, styleUrls: ['./app.component.css'],})export class AppComponent { title = 'homes';}- Your code may already be up-to-date but confirm to be sure. 
 
Summary: In this lesson you added routing to show details pages.
You now know how to:
- use route parameters to pass data to a route
- use the routerLinkdirective to use dynamic data to create a route
- use route parameter to retrieve data from the HousingServiceto display specific housing location information.
Really great work so far.
For more information about the topics covered in this lesson, visit: