Submodule 21.2: Single Page Applications - Practice

Site: ΕΛ/ΛΑΚ Moodle
Course: Study / Web Design and Web Development
Book: Submodule 21.2: Single Page Applications - Practice
Printed by: Guest user
Date: Thursday, 9 May 2024, 2:34 PM

Introduction

In this submodule, you will integrate the dishdetail component into your application. You will use a route parameter in the URL to pass in the details of the selected dish to the dishdetail component. You will:

  • Configure the routes in your router module to enable the use of route parameters within the URL to pass information to a component.

In this image you can see the parameter for the "45% MILK CHOCOLATE" which is 2. Every Choco-dish has its own parameter.

Update the dishService

Now update the dishService to return a specific dish as follows:

getDish(id: number): Dish {
  return DISHES.filter((dish) => (dish.id === id))[0];
}

Here we use the filter JavaScript method to create a new array.

We use arrow function to select the elements from that array that match the criteria that we have specified. In this case, the criteria is that dish.id should be equal and of the same type with id. Each Choco-dish has a unique id ( you can find it at dishes.ts) and thus every time that we click on a Choco-dish, they will be only one Choco-dish that will fulfill our criteria, thus the array will have only one element. However, we use [0] to specify that we want the first element of the array in order to be prepared for more complex situations. 

So this way, we will extract out that specific Choco-dish from this array and then return that dish from this getDish method.

Updating Routes

Open the routes.ts and add the following route to it:

{ path: 'dishdetail/:id', component: DishdetailComponent }

The :id in the second route is a token for a route parameter. In a URL such as /discdetail/2, "2" is the value of the id parameter. The corresponding DishdetailComponent will use that value to find and present the dish whose id is 2. 

If you tell the router to navigate to the detail component and display "75% DARK CHOCOLATE", you expect a dish id to appear in the browser URL like this:

http://localhost:4200/dishdetail/2
If a user enters that URL into the browser address bar, the router should recognize the pattern and go to the same "75% DARK CHOCOLATE" detail view.

Updating MenuComponent

 Open menu.component.html and update it as follows.

<div class="media" *ngFor="let dish of dishes" [routerLink]="['/dishdetail', dish.id]">

As you can see, we have replace the (click) = "onSelect(dish)" with the [routerLink]="['/dishdetail', dish.id. This link parameters array holds the information for router navigation. Every time that we click on a Choco-dish the router knowns to which element we are referring and provides the path to the destination component.

Also remove the <app-dishdetail> from the template because we no longer need it. Its job will be done from the router.

Open menu.component.ts and delete the selectDish variable and the onSelectDish method. Since we no longer use the (click) = "onSelect(dish)" method to select a dish,we no longer need the onSelect method.

Updating DishDetail Component

Open dishdetail.component.ts and delete input because, since we no longer use app-dishdetail in the template, we don't need it.

Then update it as follows:

. . .
import { DishService } from '../services/dish.service';
import { Params, ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
. . .
export class DishdetailComponent implements OnInit {
  dish: Dish;
  constructor(private dishservice: DishService,
    private route: ActivatedRoute,
    private location: Location) { }
  ngOnInit() {
    const id = +this.route.snapshot.params['id'];
    this.dish = this.dishservice.getDish(id);
}
  goBack(): void {
    this.location.back();
  }
}

As you can see we import the { Params, ActivatedRoute } from '@angular/router';. We do that in order to use snapshot. Let's see what snapshot does:

This application won't re-use the same instance of DishdetailComponent. The user always returns to the Choco-dish MenuComponent page to select another Choco-dish to view. There's no way to navigate from one Choco-dish detail to another without visiting the menu component in between. Therefore, the router creates a new DishdetailComponent instance every time.

Navigating back to the MenuComponent

We also import the { Location } from '@angular/common';, in order to be able to hold the current id of our location and thus be able to use the goBack() method/

The DishdetailComponent has a "Back" button that navigates imperatively back to the MenuComponent.

Open dishdetail.component.html and update it as follows:

<a (click)="goBack()" class="card-link btn btn-primary btn-sm">BACK</a>

 

The results

With the previous code configured, open your Terminal, go to the angularChocoYourname  angular-sub-folder and run ng serve to run your application in development mode. In your browser navigate to the URL localhost:4200 

Do a Git commit with the message "Angular SPA".

  • See more about Single Page Applications