In this part we will add the ability to upload product images, but first – since we now have the ability to store multiple images for a product – lets add a gallery into the product details section.

Install ngx-gallery to the app. The original verison of this gallery has been abandoned by the author but its still the most convenient gallery package I have found so we will make use of one of the forks of this that has been updated to work with Angular 9. Run the following in the client folder:

npm install @kolkov/ngx-gallery

Then lets import this into the Shared module and export it for use:

import {NgxGalleryModule} from '@kolkov/ngx-gallery';

@NgModule({
  declarations: [PagingHeaderComponent, PagerComponent, OrderTotalsComponent, TextInputComponent, StepperComponent, BasketSummaryComponent],
  imports: [
    // omitted
    NgxGalleryModule
  ],
  exports: [
    // omitted
    NgxGalleryModule
  ]
})
export class SharedModule { }

We also need to update our product.ts as we now are getting a photo collection along with the products from the API. Update the product.ts class for the IProduct and the IPhoto:

export interface IProduct {
  id: number;
  name: string;
  description: string;
  price: number;
  pictureUrl: string;
  productType: string;
  productBrand: string;
  photos: IPhoto[];
}

export interface IPhoto {
  id: number;
  pictureUrl: string;
  fileName: string;
  isMain: boolean;
}

Now we can update the product-details.component.ts to make use of the gallery package that we have installed. This one is pretty easy to use and if you wanted to do any tweaking to this then the GitHub page has the documentation. Our needs are fairly simple here and we need to provide the Gallery with some options, and of course the images which we can get from the product.photos we are returning from the API:

import {NgxGalleryAnimation, NgxGalleryImage, NgxGalleryImageSize, NgxGalleryOptions} from '@kolkov/ngx-gallery';

@Component({
  selector: 'app-product-details',
  templateUrl: './product-details.component.html',
  styleUrls: ['./product-details.component.scss']
})
export class ProductDetailsComponent implements OnInit {
  product: IProduct;
  quantity = 1;
  galleryOptions: NgxGalleryOptions[];
  galleryImages: NgxGalleryImage[];

// omitted

ngOnInit() {
    this.loadProduct();
  }

  initializeGallery() {
    this.galleryOptions = [
      {
        width: '500px',
        height: '600px',
        imagePercent: 100,
        thumbnailsColumns: 4,
        imageAnimation: NgxGalleryAnimation.Fade,
        imageSize: NgxGalleryImageSize.Contain,
        thumbnailSize: NgxGalleryImageSize.Contain,
        preview: false
      }
    ];
    this.galleryImages = this.getImages();
  }

  getImages() {
    const imageUrls = [];
    for (const photo of this.product.photos) {
      imageUrls.push({
        small: photo.pictureUrl,
        medium: photo.pictureUrl,
        big: photo.pictureUrl,
      });
    }
    return imageUrls;
  }

// omitted

  loadProduct() {
    this.shopService.getProduct(+this.activateRoute.snapshot.paramMap.get('id')).subscribe(product => {
      this.product = product;
      this.bcService.set('@productDetails', product.name);
      this.initializeGallery();
    }, error => {
      console.log(error);
    });
  }

So in here we are adding 2 class properties for the galleryOptions and galleryImages which we need to pass to the ngx-gallery component in the HTML. When we have received the product back from the API we will then initialize the gallery with the product images.

Then we need to add the ngx-gallery component to the HTML. Replace the existing image tag with this component:

<div class="row" *ngIf="product">
        <div class="col-6">
          <ngx-gallery [options]="galleryOptions" [images]="galleryImages" style="display: inline-block; margin-bottom: 20px"></ngx-gallery>
        </div>

We should now see that we have our gallery in place – admittedly things do not look too much different as we only have a single image for each product.

But it’s a start. In the next part we will look at how we can upload images to the API.

The commit for this part can be found here.