Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 4x 4x 4x 4x 4x 4x 4x 4x 4x 7x 4x 4x 4x 4x 4x 4x 4x 4x 10x 4x 4x 4x 4x 4x 4x 8x 4x | import { ChangeDetectionStrategy, Component, DestroyRef, Input, OnInit, inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject, Observable } from 'rxjs'; import { concatMap, map, take, withLatestFrom } from 'rxjs/operators'; import { ShoppingFacade } from 'ish-core/facades/shopping.facade'; import { ProductListingID, ProductListingView } from 'ish-core/models/product-listing/product-listing.model'; import { ViewType } from 'ish-core/models/viewtype/viewtype.types'; import { whenFalsy, whenTruthy } from 'ish-core/utils/operators'; @Component({ selector: 'ish-product-listing', templateUrl: './product-listing.component.html', changeDetection: ChangeDetectionStrategy.OnPush, // merged query parameters for product detail links are needed to apply previously selected filter options for variation masters too providers: [{ provide: 'PRODUCT_QUERY_PARAMS_HANDLING', useValue: 'merge' }], }) export class ProductListingComponent implements OnInit { @Input() categoryId: string; // TODO: make this a proper signal with the next Angular version @Input() set productListingId(value: ProductListingID) { this.productListingId$.next(value); } @Input() mode: 'endless-scrolling' | 'paging' = 'endless-scrolling'; @Input() fragmentOnRouting = 'product-list-top'; productListingView$: Observable<ProductListingView>; viewType$: Observable<ViewType>; listingLoading$: Observable<boolean>; currentPage$: Observable<number>; sortBy$: Observable<string>; private productListingId$ = new BehaviorSubject<ProductListingID>(undefined); private destroyRef = inject(DestroyRef); constructor(private shoppingFacade: ShoppingFacade, private router: Router, private activatedRoute: ActivatedRoute) {} ngOnInit() { this.viewType$ = this.shoppingFacade.productListingViewType$; this.listingLoading$ = this.shoppingFacade.productListingLoading$; this.currentPage$ = this.activatedRoute.queryParamMap.pipe(map(params => +params.get('page') || 1)); this.sortBy$ = this.activatedRoute.queryParamMap.pipe(map(params => params.get('sorting'))); this.productListingView$ = this.shoppingFacade.productListingView$(this.productListingId$); // append view queryParam to URL if none is set this.activatedRoute.queryParamMap .pipe( map(params => params.has('view')), take(1), whenFalsy(), concatMap(() => this.viewType$.pipe(whenTruthy(), take(1))), takeUntilDestroyed(this.destroyRef) ) .subscribe(view => this.changeViewType(view)); } /** * Emits the event for switching the view type of the product list. * * @param view The new view type. */ private changeViewType(view: ViewType) { this.router.navigate([], { relativeTo: this.activatedRoute, replaceUrl: true, queryParamsHandling: 'merge', queryParams: { view }, }); } /** * Emits the event for loading more products. */ loadMoreProducts(direction: 'up' | 'down') { this.productListingView$ .pipe( take(1), map(view => (direction === 'down' ? view.nextPage() : view.previousPage())), whenTruthy(), withLatestFrom(this.productListingId$), takeUntilDestroyed(this.destroyRef) ) .subscribe(([page, id]) => { this.shoppingFacade.loadMoreProducts(id, page); }); } get isEndlessScrolling() { return this.mode === 'endless-scrolling'; } get isPaging() { return !this.isEndlessScrolling; } } |