File

projects/storefrontlib/cms-components/product/product-list/container/product-scroll/product-scroll.component.ts

Implements

OnDestroy

Metadata

selector cx-product-scroll
templateUrl ./product-scroll.component.html

Index

Properties
Methods
Inputs
Accessors

Constructor

constructor(productListComponentService: ProductListComponentService, ref: ChangeDetectorRef)
Parameters :
Name Type Optional
productListComponentService ProductListComponentService No
ref ChangeDetectorRef No

Inputs

inputViewMode
model
scrollConfig

Methods

Private infiniteScrollOperations
infiniteScrollOperations(inputModel: ProductSearchPage)
Parameters :
Name Type Optional
inputModel ProductSearchPage No
Returns : void
loadNextPage
loadNextPage(pageNumber: number)
Parameters :
Name Type Optional
pageNumber number No
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
Private resetListOnViewModeChange
resetListOnViewModeChange()
Returns : void
scrollPage
scrollPage(pageNumber: number)
Parameters :
Name Type Optional
pageNumber number No
Returns : void
scrollToTop
scrollToTop()
Returns : void
Private setComponentConfigurations
setComponentConfigurations(scrollConfig: ViewConfig)
Parameters :
Name Type Optional
scrollConfig ViewConfig No
Returns : void
Private setConditions
setConditions()
Returns : void

Properties

appendProducts
Default value : false
inputViewMode
Type : ViewModes
isEmpty
Default value : false
isLastPage
Default value : false
isMaxProducts
Default value : false
maxProducts
Type : number
model
Type : ProductSearchPage
productLimit
Type : number
resetList
Default value : false
Private subscription
Default value : new Subscription()
viewMode
Type : ViewModes
ViewModes
Default value : ViewModes

Accessors

setConfig
setsetConfig(inputConfig: ViewConfig)
Parameters :
Name Type Optional
inputConfig ViewConfig No
Returns : void
setModel
setsetModel(inputModel: ProductSearchPage)
Parameters :
Name Type Optional
inputModel ProductSearchPage No
Returns : void
setViewMode
setsetViewMode(inputViewMode: ViewModes)
Parameters :
Name Type Optional
inputViewMode ViewModes No
Returns : void
import { Component, Input, OnDestroy, ChangeDetectorRef } from '@angular/core';
import { ProductSearchPage } from '@spartacus/core';
import { ViewModes } from '../../product-view/product-view.component';
import { Subscription } from 'rxjs';
import { ProductListComponentService } from '../product-list-component.service';
import { ViewConfig } from '../../../../../shared/config/view-config';

@Component({
  selector: 'cx-product-scroll',
  templateUrl: './product-scroll.component.html',
})
export class ProductScrollComponent implements OnDestroy {
  private subscription = new Subscription();

  @Input('scrollConfig')
  set setConfig(inputConfig: ViewConfig) {
    this.setComponentConfigurations(inputConfig);
  }

  model: ProductSearchPage;
  @Input('model')
  set setModel(inputModel: ProductSearchPage) {
    this.infiniteScrollOperations(inputModel);
  }

  inputViewMode: ViewModes;
  @Input('inputViewMode')
  set setViewMode(inputViewMode: ViewModes) {
    this.inputViewMode = inputViewMode;
    //If viewMode is already set (meaning it is not the first load)
    //Reset the product list
    if (this.viewMode) {
      this.resetListOnViewModeChange();
    } else {
      //If viewMode is not set (meaning it is the first load)
      //Set the viewMode
      this.viewMode = inputViewMode;
    }
  }

  viewMode: ViewModes;
  productLimit: number;
  maxProducts: number;

  ViewModes = ViewModes;
  appendProducts = false;
  resetList = false;
  isMaxProducts = false;
  isLastPage = false;
  isEmpty = false;

  constructor(
    private productListComponentService: ProductListComponentService,
    private ref: ChangeDetectorRef
  ) {}

  scrollPage(pageNumber: number): void {
    this.appendProducts = true;
    this.ref.markForCheck();
    this.productListComponentService.getPageItems(pageNumber);
  }

  loadNextPage(pageNumber: number): void {
    this.isMaxProducts = false;
    this.scrollPage(pageNumber);
  }

  scrollToTop(): void {
    window.scroll(0, 0);
  }

  private setComponentConfigurations(scrollConfig: ViewConfig): void {
    const isButton = scrollConfig.view?.infiniteScroll?.showMoreButton;
    const configProductLimit = scrollConfig.view?.infiniteScroll?.productLimit;

    //Display "show more" button every time when button configuration is true
    //Otherwise, only display "show more" when the configuration product limit is reached
    this.productLimit = isButton ? 1 : configProductLimit;
  }

  private infiniteScrollOperations(inputModel: ProductSearchPage): void {
    if (this.appendProducts) {
      this.model = {
        ...inputModel,
        products: this.model.products.concat(inputModel.products),
      };
    } else {
      this.model = inputModel;
      this.maxProducts = this.productLimit;
    }
    this.setConditions();
    this.ref.markForCheck();
  }

  private resetListOnViewModeChange(): void {
    this.scrollToTop();
    this.resetList = true;
    this.productListComponentService.getPageItems(0);
  }

  //Set booleans after model has been retrieved
  private setConditions(): void {
    this.isEmpty = !this.model.products || this.model.products.length === 0;

    this.isLastPage =
      this.model.pagination.currentPage ===
      this.model.pagination.totalPages - 1;

    this.isMaxProducts =
      this.productLimit &&
      this.productLimit !== 0 &&
      this.model.products.length >= this.maxProducts;

    //Add the productLimit to the current number of products to determine the next max number of products
    if (this.isMaxProducts) {
      this.maxProducts = this.model.products.length + this.productLimit;
    }

    //Only change viewMode once the new model is set
    //This prevents flickering issues
    if (this.viewMode !== this.inputViewMode) {
      this.viewMode = this.inputViewMode;
    }

    this.resetList = false;
    this.appendProducts = false;
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}
<ng-container *ngIf="viewMode === ViewModes.Grid">
  <div
    infiniteScroll
    [infiniteScrollDistance]="5"
    [infiniteScrollThrottle]="50"
    [infiniteScrollDisabled]="isMaxProducts || isLastPage || isEmpty"
    (scrolled)="scrollPage(model?.pagination?.currentPage + 1)"
  >
    <div class="row">
      <cx-product-grid-item
        *ngFor="let product of model?.products"
        [product]="product"
        class="col-12 col-sm-6 col-md-4"
      ></cx-product-grid-item>
    </div>
    <div
      [className]="
        !isLastPage && model?.pagination?.currentPage > 0
          ? 'cx-double-btn-container grid-btn-padding'
          : 'cx-single-btn-container grid-btn-padding'
      "
    >
      <div
        *ngIf="
          (isMaxProducts || isLastPage) && model?.pagination?.currentPage > 0
        "
        (click)="scrollToTop()"
        class="btn btn-block btn-action"
      >
        {{ 'productList.backToTopBtn' | cxTranslate }}
      </div>
      <div
        *ngIf="isMaxProducts && !isLastPage"
        (click)="loadNextPage(model?.pagination?.currentPage + 1)"
        class="btn btn-block btn-action align-btn"
      >
        {{ 'productList.showMoreBtn' | cxTranslate }}
      </div>
    </div>
    <div *ngIf="appendProducts" class="cx-spinner">
      <cx-spinner></cx-spinner>
    </div>
  </div>
</ng-container>

<ng-container *ngIf="viewMode === ViewModes.List">
  <div
    infiniteScroll
    [infiniteScrollDistance]="3"
    [infiniteScrollThrottle]="50"
    [infiniteScrollDisabled]="isMaxProducts || isLastPage || isEmpty"
    (scrolled)="scrollPage(model?.pagination?.currentPage + 1)"
  >
    <cx-product-list-item
      *ngFor="let product of model?.products"
      [product]="product"
      class="cx-product-search-list"
    ></cx-product-list-item>
    <div
      [className]="
        !isLastPage && model?.pagination?.currentPage > 0
          ? 'cx-double-btn-container'
          : 'cx-single-btn-container'
      "
    >
      <div
        *ngIf="
          (isMaxProducts || isLastPage) && model?.pagination?.currentPage > 0
        "
        (click)="scrollToTop()"
        class="btn btn-block btn-action"
      >
        {{ 'productList.backToTopBtn' | cxTranslate }}
      </div>
      <div
        *ngIf="isMaxProducts && !isLastPage"
        (click)="loadNextPage(model?.pagination?.currentPage + 1)"
        class="btn btn-block btn-action align-btn"
      >
        {{ 'productList.showMoreBtn' | cxTranslate }}
      </div>
    </div>
    <div *ngIf="appendProducts" class="cx-spinner">
      <cx-spinner></cx-spinner>
    </div>
  </div>
</ng-container>
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""