Harvey
Harvey

Reputation: 572

ReferenceError: document is not defined while using Angular 8 NgxUsefulSwiper

I have a component which uses the library NgxUsefulSwiper. It's working fine on my local enviroment but we're getting the following error while trying to reach the page with the component on development enviroment:

ReferenceError: document is not defined
    at Swiper.destroy (/opt/app/dist/ozdstore/ssr/server.js:253982:11)
    at /opt/app/dist/ozdstore/ssr/server.js:247115:26
    at Array.forEach (<anonymous>)
    at /opt/app/dist/ozdstore/ssr/server.js:247114:20
    at Array.forEach (<anonymous>)
    at Swiper.emit (/opt/app/dist/ozdstore/ssr/server.js:247108:19)
    at Swiper.destroy (/opt/app/dist/ozdstore/ssr/server.js:250412:16)
    at SwiperComponent.ngOnDestroy (/opt/app/dist/ozdstore/ssr/server.js:234798:21)
    at callProviderLifecycles (/opt/app/dist/ozdstore/ssr/server.js:103382:18)
    at callElementProvidersLifecycles (/opt/app/dist/ozdstore/ssr/server.js:103341:13)

I don't understand the reason for this since I can't see any type of error on my local server, and other pages using swiper seem to work without problem. Here is my code;

brands-top-area.component.html

<div class="brand-main-area">
  <div class="brand-top-area">
    <div class="container">
      <h1 class="title">Markalar</h1>
      <div class="form-area">
        <label class="search-label">
          <i class="icon icon-search-18_3"></i>
          <input type="search" name="search" placeholder="Marka Ara">
        </label>
      </div>
      <div class="banner-product-card-area brand-card">
        <div class="banner-product-card-container">
          <!-- Swiper -->
          <swiper [config]="config" class="swiper-container">
            <div class="swiper-wrapper">
              <div class="swiper-slide" *ngFor="let brand of this.brands$ | async">
                <a (click)="this.redirectToSearchPage(brand.name)" title="" class="banner-brand-card">
                  <figure class="product-logo">
                    <img [src]="getLogoImage(brand.image?.url)" alt="">
                  </figure>
                </a>
              </div>
            </div>
          </swiper>
          <!-- Add Arrows -->
          <div class="swiper-button-next next-button"></div>
          <div class="swiper-button-prev prev-button"></div>
        </div>
      </div>
    </div>
  </div>
</div>

brands-top-area.component.ts

import {Component, OnInit} from '@angular/core';
import {SwiperOptions} from 'swiper';
import {HttpClient} from '@angular/common/http';
import {CustomOccEndpointsService} from '../../occ/custom-occ-endpoints.service';
import {Category, OccConfig, RoutingService} from '@spartacus/core';
import {map} from 'rxjs/operators';
import {Observable} from 'rxjs';

@Component({
  selector: 'app-brands-top-area',
  templateUrl: './brands-top-area.component.html',
  styleUrls: ['./brands-top-area.component.scss']
})
export class BrandsTopAreaComponent implements OnInit {

  brands$: Observable<Category[]>;

  config: SwiperOptions = {
    slidesPerView: 5,
    spaceBetween: 0,
    direction: 'horizontal',
    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev',
    }
  };

  constructor(private http: HttpClient,
              private endPointsService: CustomOccEndpointsService,
              protected occConfig: OccConfig,
              protected routingService: RoutingService) {

  }
  ngOnInit(): void {
    this.brands$ = this.getBrands();
  }

  getBrands() : Observable<Category[]> {
    return this.http.get(this.endPointsService.getUrl('categories/brands/brands')).pipe(map((res: any) => res.categoryList));
  }

  redirectToSearchPage(brand: string): void {
    this.routingService.go({
        cxRoute: 'search',
        params: {
          query: '',
        },
      },
      {},
      {
        queryParams: {
          query: ':relevance:brandName:' + brand
        }
      },
    );
  }

  getLogoImage(url: string): string {
    if (!url) {
      return null;
    }
    return url.startsWith('http') ? url : this.getBaseUrl() + url;
  }

  private getBaseUrl(): string {
    return (
      this.occConfig.backend.media.baseUrl || this.occConfig.backend.occ.baseUrl || ''
    );
  }
}

Upvotes: 0

Views: 1274

Answers (1)

tobi-or-not-tobi
tobi-or-not-tobi

Reputation: 1260

The error is crated on the SSR server. This server doesn't have some browser APIs, such as document.

The angular documentation describes this in more detail, see https://angular.io/guide/universal

Because a Universal app doesn't execute in the browser, some of the browser APIs and capabilities may be missing on the server.

For example, server-side applications can't reference browser-only global objects such as window, document, navigator, or location.

There's also a page in the docs of Spartacus that highlight to avoid direct usage of these APIs when those are not available, see https://sap.github.io/spartacus-docs/server-side-rendering-coding-guidelines/.

Upvotes: 2

Related Questions