Chapter 9 - Define and access multiple slideshows¶
In this chapter, you will define and access multiple slideshows. This will allow you to create diverse slideshows that you can show in different contexts without the need to change them every time.
Update the AppService to define two different slideshows with the updated Slideshow type. In this example, the main slideshow is split into two slideshows. The slideshows are then saved in a Map with a key that identifies each slideshow. The method getSlideshows allows to get all the slideshows.
import{Injectable}from'@nestjs/common';import{MediaType}from'./enums/media-type.enum';import{Slideshow}from'./types/slideshow.type';constslideshow1:Slideshow={// (1)!id:'slideshow1',slides:[{src:"https://source.unsplash.com/random?1",type:MediaType.IMAGE,alt:"Random photo on Unsplash",},{src:"https://source.unsplash.com/random?2",type:MediaType.IMAGE,alt:"Random photo on Unsplash",interval:2000,},]}constslideshow2:Slideshow={// (2)!id:'slideshow2',slides:[{src:"https://source.unsplash.com/random?3",type:MediaType.IMAGE,alt:"Random photo on Unsplash",},{src:"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/Sintel.mp4",type:MediaType.VIDEO,alt:"Sintel: first open movie",interval:10000,},]}constslideshows:Map<string,Slideshow>=newMap([// (3)![slideshow1.id,slideshow1],[slideshow2.id,slideshow2],]);@Injectable()exportclassAppService{getSlideshows(){returnslideshows;// (4)!}getSlideshow(slideshowId:string){// (5)!constslideshow=slideshows.get(slideshowId);returnslideshow;// (6)!}}
Define the first slideshow.
Define the second slideshow.
The slideshows are saved in a Map. The first slideshow has the ID slideshow1. The second has the ID slideshow2.
The slideshows are returned.
The slideshow ID parameter (slideshowId) defines the slideshow to get from the Map.
The second route has a little catch. What if the ID of the slideshow doesn't exist or is not existent? A simple solution would be to check if the slideshow requested by the user exists. If it doesn't exist, redirect the user to the page listing the slideshows to allow them to select a correct one.
import{Get,Controller,Render,Param,Res}from'@nestjs/common';// (1)!import{Response}from'express';// (2)!import{AppService}from'./app.service';@Controller()exportclassAppController{constructor(privatereadonlyappService:AppService){}@Get()@Render('index')getSlideshows(){constslideshows=this.appService.getSlideshows();// TODO: This can be improved when the following pull request is merged:// https://github.com/handlebars-lang/handlebars.js/pull/1679constslideshowsAsArray=Array.from(slideshows).map(([key,value])=>({id:key,slideshow:value,}))// (3)!return{slideshows:slideshowsAsArray};}@Get(':id')// (4)!getSlideshow(@Res()res:Response/* (5)! */,@Param('id')id:string/* (6)! */){constslideshow=this.appService.getSlideshow(id);if(!slideshow){// (7)!returnres.redirect('/');// (8)!}returnres.render(// (9)!'slideshow',{slideshow:slideshow},);}}
Import missing dependencies to access the response to send to the user.
Get the type of the response so Visual Studio Code knows the typing of res.redirect.
This is a workaround as Handlebars doesn't support Map for the moment.
Remove @Render('slideshow') to dynamically render it later.
The @Res()res:Response is a decorator to extract the response that can be sent to the user.
The @Param('id')id:string is a decorator to extract the id from the user's request.
Check if the slideshow exists.
If it doesn't exist, redirect the user to the main page (/).
Return the slideshow if it exists with the slideshow Handlebars template.
Update the main template to list all available slideshows¶
The main page (/) will now list all available slideshows with links to access the slideshows.
<!DOCTYPE html><html><head><metacharset="utf-8"/><title>Media Player</title></head><body> {{!--
TODO: This can be improved when the following pull request is merged:
https://github.com/handlebars-lang/handlebars.js/pull/1679
--}}
{{#each slideshows}}
<p><ahref="/{{this.id}}">Access slideshow '{{this.id}}'.</a></p> {{else}} <!-- (1)! --><p>No slideshow.</p> {{/each}}
</body></html>
If no slideshows are available, the message No slideshow. will be shown to inform the user.
Start the application and access http://localhost:3000. You should see a list with the two slideshows. Access the first to see the two images slideshow. Access the second to see an image and a video slideshow.
Congrats! You can now define and access multiple slideshows. Your application list all available slideshows and you can choose which one you'd like to display. If a user tries to access a wrong slideshow ID, they will be redirected to the main page will all available slideshows.
Can you create a 404 page to display a custom message when you try to access an inexistent slideshow? You can check the NestJS - MVC #Dynamic template rendering documentation for resources.
Show me the answer!
Create a new views/404.hbs Handlebars template. This template will display an error message and a link to go back to the main page.
<!DOCTYPE html><html><head><metacharset="utf-8"/><title>Media Player</title></head><body><p>This slideshow doesn't exist.</p><p><ahref="/">Go back to homepage.</a></p></body></html>
Update the AppController to render the 404 Handlebars when a slideshow wasn't found.
Save your changes. If you didn't stop your NestJS application, it should automatically restart the application. Access http://localhost:3000/non-existing-slideshow, you should see the error message. You can then go back to the main page.