File
Metadata
| changeDetection |
ChangeDetectionStrategy.OnPush |
| selector |
cx-product-images |
| templateUrl |
./product-images.component.html |
Methods
|
Private
createThumbs
|
createThumbs(product: Product)
|
|
|
Return an array of CarouselItems for the product thumbnails.
In case there are less then 2 thumbs, we return null.
Parameters :
| Name |
Type |
Optional |
| product |
Product
|
No
|
Returns : Observable[]
|
|
getActive
|
getActive(thumbs: any[])
|
|
|
find the index of the main media in the list of media
Parameters :
| Name |
Type |
Optional |
| thumbs |
any[]
|
No
|
Returns : Observable<number>
|
|
isActive
|
isActive(thumbnail: ImageGroup)
|
|
|
|
Returns : Observable<boolean>
|
|
openImage
|
openImage(item: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| item |
any
|
No
|
|
|
mainImage$
|
Default value : combineLatest([this.product$, this.mainMediaContainer]).pipe(
map(([, container]) => container)
)
|
|
|
|
Protected
mainMediaContainer
|
Default value : new BehaviorSubject<any>(null)
|
|
|
|
Protected
product$
|
Type : Observable<Product>
|
Default value : this.currentProductService
.getProduct()
.pipe(
filter(isNotNullable),
distinctUntilChanged(),
tap((p: Product) => {
this.mainMediaContainer.next(p.images?.PRIMARY ? p.images.PRIMARY : {});
})
)
|
|
|
|
thumbs$
|
Type : Observable<any[]>
|
Default value : this.product$.pipe(
map((p: Product) => this.createThumbs(p))
)
|
|
|
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ImageGroup, isNotNullable, Product } from '@spartacus/core';
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators';
import { CurrentProductService } from '../current-product.service';
@Component({
selector: 'cx-product-images',
templateUrl: './product-images.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductImagesComponent {
protected mainMediaContainer = new BehaviorSubject<any>(null);
protected product$: Observable<Product> = this.currentProductService
.getProduct()
.pipe(
filter(isNotNullable),
distinctUntilChanged(),
tap((p: Product) => {
this.mainMediaContainer.next(p.images?.PRIMARY ? p.images.PRIMARY : {});
})
);
thumbs$: Observable<any[]> = this.product$.pipe(
map((p: Product) => this.createThumbs(p))
);
mainImage$ = combineLatest([this.product$, this.mainMediaContainer]).pipe(
map(([, container]) => container)
);
constructor(protected currentProductService: CurrentProductService) {}
openImage(item: any): void {
this.mainMediaContainer.next(item);
}
isActive(thumbnail: ImageGroup): Observable<boolean> {
return this.mainMediaContainer.pipe(
filter(Boolean),
map((container: any) => {
return (
container.zoom &&
container.zoom.url &&
thumbnail.zoom &&
thumbnail.zoom.url &&
container.zoom.url === thumbnail.zoom.url
);
})
);
}
/** find the index of the main media in the list of media */
getActive(thumbs: any[]): Observable<number> {
return this.mainMediaContainer.pipe(
filter(Boolean),
map((container: any) => {
const current = thumbs.find(
(t) =>
t.media &&
container.zoom &&
t.media.container &&
t.media.container.zoom &&
t.media.container.zoom.url === container.zoom.url
);
return thumbs.indexOf(current);
})
);
}
/**
* Return an array of CarouselItems for the product thumbnails.
* In case there are less then 2 thumbs, we return null.
*/
private createThumbs(product: Product): Observable<any>[] {
if (
!product.images ||
!product.images.GALLERY ||
product.images.GALLERY.length < 2
) {
return [];
}
return (<any[]>product.images.GALLERY).map((c) => of({ container: c }));
}
}
<ng-container *ngIf="mainImage$ | async as main">
<cx-media [container]="main"></cx-media>
</ng-container>
<ng-container *ngIf="thumbs$ | async as thumbs">
<cx-carousel
*ngIf="thumbs.length"
class="thumbs"
[items]="thumbs"
itemWidth="120px"
[hideIndicators]="false"
[template]="thumb"
></cx-carousel>
</ng-container>
<ng-template #thumb let-item="item">
<cx-media
[container]="item.container"
tabindex="0"
(focus)="openImage(item.container)"
[class.is-active]="isActive(item.container) | async"
format="product"
>
</cx-media>
</ng-template>
Legend
Html element with directive