Angular 17 window not defined
Asked Answered
E

8

6

Recently after updating my angular cli from 16 to 17 I have been facing performance issues and I had no idea what is SSR and prerendering so I left them enabled. But the root cause was ssr.

  • After installing materialize-css I was getting an error M is not defined. Then I imported it from materialize-css.

  • Again I was getting an error window is not defined

Engorge answered 20/11, 2023 at 8:8 Comment(0)
E
-4

I disabled SSR in my angular.json

"server": "src/main.server.ts",
            "prerender": true,
            "ssr": {
              "entry": "server.ts"
            }

to

"server": "src/main.server.ts",
              "prerender": false,
              "ssr": false
Engorge answered 20/11, 2023 at 8:8 Comment(3)
i am not sure this solution right way or not. but its works for meLanni
This is not the correct solution if you want ssrJair
This is not about how to enable ssrEngorge
B
6

I was getting the same error in Angular 17.

This solution worked for me:

if (typeof window !== "undefined") {
   // browser code
}

Source: https://dev.to/vvo/how-to-solve-window-is-not-defined-errors-in-react-and-next-js-5f97 Author: Vincent Voyer

Byram answered 6/2, 2024 at 13:43 Comment(2)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Perquisite
i too got same problem,finally i had to write logic in .ts file itself. (Since i wanted it to run every time user log's in or out i written it inside Onchanges function itself-->if(changes['loggedIn']))Hyperopia
S
5

When using Server side rendering (SSR) and/or prerendering, the app will run on a node environment where the global window object isn't defined.

If you want to keep using SSR/prenrender and still access window you can use afterNextRender() which will be invoked on the browser side only (the callback will be run outside the Angular zone, you also might need ngZone.run().)

Saccharify answered 20/11, 2023 at 8:35 Comment(0)
A
4

You can also create a token for the window, just as Angular does for the Document:

import { InjectionToken } from '@angular/core';

export const WINDOW = new InjectionToken<Window>('WindowToken', {
  factory: () => {
    if(typeof window !== 'undefined') {
      return window
    }
    return new Window(); // does this work?
  }
});

Then you can inject it in the places you need the window object like so:

@Component({
  selector: 'my-component',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './my-component.component.html',
  styleUrl: './my-component.component.scss',
})
export class RegistrationFormComponent {
  private _window = inject(WINDOW); // or window = inject(WINDOW);

  inSomeFunction() {
    this._window.location.assign('my.url')
  }
}

This way, you can keep the benefits of SSR and prerendering and use the window object.

Allistir answered 19/4, 2024 at 14:40 Comment(0)
B
2

I had the same problem and worked around the problem by using ChangeDetectorRef:

export class ApplicationLayoutComponent implements OnInit {
  screenWidth!: number;
  injector = inject(Injector);
  @ViewChild('sidebar') sidebar!: ElementRef;

  @HostListener('window:resize', ['$event'])

  onResize(event: Event) {
    this.screenWidth = window.innerWidth;
  }

  constructor(private cd : ChangeDetectorRef) {
    
  }
  ngOnInit(): void {
    afterNextRender(() => 
      this.changeScreenWidth(),
      {injector: this.injector, phase: AfterRenderPhase.Read}          
    );
  }

  changeScreenWidth() {
    this.screenWidth = window.innerWidth;    
    this.cd.detectChanges();
  }
Banded answered 6/3, 2024 at 21:11 Comment(0)
Y
0

Import Platform ID and isPlatformBrower from angular. And check for the condition of isBrowser variable.

import {  PLATFORM_ID,  Inject } from '@angular/core';
import { DOCUMENT, isPlatformBrowser } from '@angular/common';

constructor(
    @Inject(DOCUMENT) private dom: Document,
    @Inject(PLATFORM_ID) private platformId: Object,
  ) {
    this.isBrowser = isPlatformBrowser(platformId);
    if (this.isBrowser) {
      window.addEventListener(
        'message',
        (e) => {
          console.log(e.data);
        },
        false
      );
    }
  }
Yelenayelich answered 5/4, 2024 at 13:25 Comment(0)
G
0

This worked for my Angular 17.3.8 application with SSR active:

import { InjectionToken } from "@angular/core";

export const WINDOW = new InjectionToken<Window>("WINDOW", {
  factory: () => (typeof window !== "undefined" ? window : ({} as Window)),
});
Gerald answered 17/6, 2024 at 3:57 Comment(0)
S
0

Just use globalThis.window instead of window and its done

Spathic answered 20/10, 2024 at 4:42 Comment(0)
E
-4

I disabled SSR in my angular.json

"server": "src/main.server.ts",
            "prerender": true,
            "ssr": {
              "entry": "server.ts"
            }

to

"server": "src/main.server.ts",
              "prerender": false,
              "ssr": false
Engorge answered 20/11, 2023 at 8:8 Comment(3)
i am not sure this solution right way or not. but its works for meLanni
This is not the correct solution if you want ssrJair
This is not about how to enable ssrEngorge

© 2022 - 2025 — McMap. All rights reserved.