Skip to content
View lessons Login

Launch sale! Get 30% OFF expires in 126:46:22

3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Creating a Slideshow

Creating a Slideshow

Although we will still have a few refinements remaining after this, in this lesson we are going to tackle the last significant feature of this application: the ability to play a slideshow of all of the photos that have been taken.

We will start with the first photo taken, and then display each photo rapidly in succession. The core idea here is reasonably straightforward, but the way in which we will achieve this using streams is actually kind of interesting and challenging. If you’re struggling with the concept of observables and streams a little, don’t fret too much over this lesson. If you’re enjoying streams and looking for a challenge, then you’re in for a treat.

Create the Slideshow Component

import { Component, inject, input } from '@angular/core';
import { PhotoData } from '../shared/interfaces/photo';
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonTitle,
IonToolbar,
ModalController,
} from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { close } from 'ionicons/icons';
@Component({
selector: 'app-slideshow',
template: `
<ion-header>
<ion-toolbar color="danger">
<ion-title>Play</ion-title>
<ion-buttons slot="end">
<ion-button (click)="modalCtrl.dismiss()">
<ion-icon name="close" slot="icon-only"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content> </ion-content>
`,
imports: [
IonHeader,
IonToolbar,
IonTitle,
IonButtons,
IonButton,
IonIcon,
IonContent,
],
})
export class SlideshowComponent {
modalCtrl = inject(ModalController);
photos = input.required<PhotoData[]>();
constructor() {
addIcons({ close });
}
}

All this should be reasonably familiar. We are setting up a component that we will display as a modal and we are setting up an input so that can pass in our photos.

The interesting part will come next.

Displaying one photo at a time

The next step is to take the photos we are passing in as an input, and somehow convert them into a stream that emits one photo at a time for us to display.

export class SlideshowComponent {
modalCtrl = inject(ModalController);
photos = input.required<PhotoData[]>();
reversedPhotos = computed(() => [...this.photos()].reverse());
currentPhoto$ = toObservable(this.reversedPhotos).pipe(
// Emit one photo at a time
switchMap((photos) => from(photos)),
concatMap((photo) =>
// Create a new stream for each individual photo
of(photo).pipe(
// Creating a stream for each individual photo
// will allow us to delay the start of the stream
delay(500),
),
),
);
currentPhoto = toSignal(this.currentPhoto$);
constructor() {
addIcons({ close });
}
}

We have our photos input signal that gets the photo values to begin with, then we derive a reversedPhotos signal from that since we want to display the photos in reverse order.

But then we convert that reversedPhotos signal into an observable stream that will emit one photo at a time from our photos array, and then we convert that result back into a signal.

Whilst the detour/conversion into observables here isn’t strictly required, I find observables to be a much more reliable and powerful solution than relying on things like

STANDARD STANDARD

Thanks for checking out the preview of this lesson!

You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).