Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Angular: cdk-virtual-scroll-viewport- scrollWindow attribute not working in angular ssr (universal), giving error- document is not defined

On using cdk-virtual-scroll-viewport in Angular SSR app and adding scrollWindow attribute, I am getting the following error:-

document is not defined
    at _CdkVirtualScrollableWindow (...\test_cdk_scroll_ssr\node_modules\@angular\cdk\fesm2022\scrolling.mjs:1659:26)
    at NodeInjectorFactory.CdkVirtualScrollableWindow_Factory (...\test_cdk_scroll_ssr\node_modules\@angular\cdk\fesm2022\scrolling.mjs:1667:14)
    at getNodeInjectable (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:5984:44)
    at searchTokensOnInjector (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:5911:16)
    at lookupTokenUsingNodeInjector (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:5860:34)
    at getOrCreateInjectable (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:5772:23)
    at ɵɵdirectiveInject (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:11050:19)
    at ɵɵinject (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:1106:42)
    at NodeInjectorFactory.factory (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:3325:29)
    at getNodeInjectable (...\test_cdk_scroll_ssr\node_modules\@angular\core\fesm2022\core.mjs:5984:44

I followed the official example of scrollWindow attribute in an SSR app and it gave me the above error. This example works fine on non SSR angular apps.

My Code (exactly same as in the example)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

app.component.ts:-

import { ChangeDetectionStrategy, Component } from '@angular/core';
import {ScrollingModule} from '@angular/cdk/scrolling';

@Component({
  selector: 'app-root',
  styleUrl: './app.component.scss',
  templateUrl: './app.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [ScrollingModule]
})
export class AppComponent {
  items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
}

app.component.html

<div class="example-header">Content before</div>
<cdk-virtual-scroll-viewport scrollWindow itemSize="50">
  <div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div>
</cdk-virtual-scroll-viewport>
<div class="example-footer">Content after</div>

app.component.scss:-

.example-item {
    height: 50px;
  }
  
  .example-header,
  .example-footer {
    height: 100px;
    background: lightgray;
  }

Maybe it does not work because window is not available on server side?

Is there any way to make the scrollWindow attribute work in Angular SSR apps? thanks!

>Solution :

Yes make the virtual scroll render only when its the browser, we can use isPlatformBrowser and solve it!

import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { NgIf } from '@angular/common';
import {ScrollingModule} from '@angular/cdk/scrolling';

@Component({
  selector: 'app-root',
  styleUrl: './app.component.scss',
  templateUrl: './app.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [ScrollingModule, NgIf]
})
export class AppComponent {
  items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
  isBrowser: boolean;

  constructor( @Inject(PLATFORM_ID) platformId: Object) {
      this.isBrowser = isPlatformBrowser(platformId);
  }
}

HTML

<ng-container *ngIf="isBrowser">
    <div class="example-header">Content before</div>
    <cdk-virtual-scroll-viewport scrollWindow itemSize="50">
      <div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div>
    </cdk-virtual-scroll-viewport>
    <div class="example-footer">Content after</div>
</ng-container>

By the way, the component works using the window or document object, so it pointless to render on the server, its a browser only functionality, due to use of window or document!

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading