3d cartoon hands holding a phone

Unlock full course by purchasing a membership

Lesson 10

Styling and Refinements

Finishing things up

STANDARD

Styling and Refinements

The application is mostly done now, all we have left to do is a few final refinements and style tweaks.

Adding Delete Functionality

Once again, we are going to use the same strategy as we did in Quicklists to delete photos from this application. We will add a method to support deleting and then trigger that delete using sliding list items.

However, there is one interesting aspect to this and that is: in the case of the application running natively, the photo will be stored in the native filesystem. We can just delete the entry from our StorageService using the Ionic Storage API, but that would only remove the path to that photo. The photo itself will still exist on the device (we can just no longer access it). To properly clean up after ourselves, we are going to again use the Filesystem API to remove the photo on the device if it exists.

Add the following method to the PhotoService:

  async deletePhoto(name: string) {
    const newPhotos = this.#photos$.value.filter(
      (photos) => photos.name !== name
    );

    this.#photos$.next(newPhotos);

    if (this.platform.is('capacitor')) {
      await Filesystem.deleteFile({
        path: name,
        directory: Directory.Data,
      });
    }
  }

The first half of this method is standard - we remove the photo and emit the new values. In the second half we check to see if this is running natively, and if it is we use the deleteFile method from the Filesystem plugin to remove the photo from the native file system as well.

Now we are going to modify our PhotoListComponent to use sliding list items and to emit an event when an item is selected to be deleted. Remember that we want to handle the actual deletion in the parent HomeComponent file which is why we create a deleted output on our dumb component, rather than just having the dumb component delete the item directly (because then it wouldn’t be a dumb component anymore!).

Add the following output to the PhotoListComponent:

@Output() delete = new EventEmitter<string>();

I will paste the code for updating to use the ion-item-sliding component in just a moment. However, this would be a good exercise if you want to try and do it for yourself (it is the same as what we did in the Quicklists application). Use the ion-item-sliding component (refer to the documentation if you need) to add a button beneath the photo items. Also trigger the delete output that we just added when this button is clicked.

Modify the PhotoListComponent template to reflect the following:

    <ion-list lines="none">
      <ion-item-sliding *ngFor="let photo of photos; trackBy: trackByFn">
        <ion-item>
          <img [src]="photo.safeResourceUrl" />
          <ion-badge slot="end" color="light">
            {{ photo.dateTaken | daysAgo }}
          </ion-badge>
        </ion-item>
        <ion-item-options side="end">
          <ion-item-option (click)="delete.emit(photo.name)" color="danger">
            <ion-icon name="trash" slot="icon-only"></ion-icon>
          </ion-item-option>
        </ion-item-options>
      </ion-item-sliding>
    </ion-list>

Finally, we will need to handle this delete output in our HomeComponent.

Update the HomeComponent to call the deletePhoto method in response to the delete event:

        <app-photo-list
          [photos]="vm.photos"
          (delete)="photoService.deletePhoto($event)"
        ></app-photo-list>

You should now be able to delete photos (note that you will need the mobile emulation in the Chrome DevTools enabled in order to slide the photos - if you try to drag the items without having the emulator enabled it will just drag the actual image).

Presenting Element for Modal

We are again going to make a similar improvement to our Quicklists application and add in the presentingElement option for our modal to make it look a bit nicer.

Add the presentingElement option to the modal in HomeComponent:

        <ion-modal
          [isOpen]="vm.modalIsOpen"
          [canDismiss]="true"
          [presentingElement]="routerOutlet.nativeEl"
          (ionModalDidDismiss)="modalIsOpen$.next(false)"
        >
STANDARD
Key

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).