Only Allow One Photo Per Day
In this lesson, we are going to implement a reasonably simple feature but one that is part of the core concept of this application: to take one photo each day. This gives us an interesting opportunity to think about streams and reactive programming.
We are really only aiming to achieve one goal here:
- If a photo has already been taken that day, disable the take photo button
We store dates with our photos already so it seems like it should be reasonably easy. You might consider that the above doesn’t seem very secure - just disabling a button doesn’t really prevent someone from doing something. However, this is a totally local application - if the user wants to hack around with the client side code so they can bypass the disabled button and take more than one photo a day it doesn’t really matter.
Getting the data from the stream
The button we want to disable is in our HomeComponent
, and in that component we have a stream of the photos$
data that we need to check the date on:
photos$ = this.photoService.photos$.pipe(
map((photos) =>
photos.map((photo) => ({
...photo,
safeResourceUrl: this.sanitizer.bypassSecurityTrustResourceUrl(
photo.path
),
}))
)
);
One thing that you could do, and perhaps this might come to you more naturally if you are used to an imperative style of programming, is to create a class member that is a boolean
flag like this:
hasTakenPhotoToday = false;
Then perhaps in an OnInit
hook you subscribe to photos$
to do the check and set it appropriately:
this.photos$.subscribe((photos) => {
this.hasTakenPhotoToday = // check dates on photos;
});
However, I would not recommend doing this. Again, we want to avoid manual subscribes wherever possible and there isn’t a need for one here.
There are actually different ways we could handle this. One method that would be fine, but which we are not doing, is to use a pipe. In the template, you might do something like this:
<ion-button (click)="photoService.takePhoto()" [disabled]="vm.photos | hasTakenPhotoToday">
<ion-icon name="camera-outline" slot="icon-only"></ion-icon>
</ion-button>