angular4 document and window are undefined

Viewed 11885

I am using dot net core with angular 4 and webpack config.

When I am trying to get the window or document in a component or service, I am getting this error:

ReferenceError: document is not defined

ReferenceError: window is not defined

Here are the errors i am getting:

Microsoft.AspNetCore.NodeServices[0]
      ERROR { ReferenceError: window is not defined
          at _window (C:\gitRepose\AngularCore\FM\FMWebApp\FootballWebApp\ClientApp\dist\main-server.js:30801:12)

Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
      An unhandled exception has occurred: window is not defined
      ReferenceError: window is not defined
    at _window (C:\gitRepose\AngularCore\FM\FMWebApp\FootballWebApp\ClientApp\dist\main-server.js:30801:12)

I am still new to the webpack stuff, anyone know how i can fix this? I need the window to handle when a window is resizing.

EDIT...

I managed to get this fixed by removing the pre render from the index.cshtml

i changed it from this:

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

to this:

<app>Loading...</app>

but now obviously pre rendering on server side won't be happening :/ thus it will slow the app boot up time, any ideas how I can fix this without loosing server side pre rendering?

8 Answers

If you're using server-side rendering, you should remove all code using window or document that run in node because node doesn't have these variables (node only have global).

If you still want to use window or document in node env, you can try to use jsdom (https://github.com/tmpvar/jsdom).

If you want to use AOT, use dependency injection to mount window into your components. In short, write a service that can provide the window object:

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

function getWindow (): any {
    return window;
}

@Injectable()
export class WindowRefService {
    get nativeWindow (): any {
        return getWindow();
    }
}

More information here.

If you want a quick fix : put this code at the top of your typescript file :

 declare var window;
 declare var document;

But if you wanna do it properly :

 import { DOCUMENT } from '@angular/platform-browser';
 export const WINDOW           = new InjectionToken( 'WINDOW' );

 @Component()
 export class YourComponent{
          constructor(
              @Inject( WINDOW ) private window,
              @Inject( DOCUMENT ) private document){}

inside your module :

providers       : [
    {
        provide  : WINDOW,
        useValue : window
    }
],

This way you can override window and document in your tests and anywhere else.

wrap your code which depends on window like below

if (typeof window !== 'undefined') {
    // your client-only logic here like below
    alert(window.innerWidth);
}

Well i'm using angular 4 application and inject the window object using:

In Component constructor( @Inject('Window') private window: Window) { }

and In module: providers: [{ provide: 'Window', useValue: window }]

and then in the component function i used it like: this.window

In Server Side JavaScript is running in Node Environment which does not have window or document object. Window & Document object works when your javascript code executes in Browser Environment. So make sure window or document object related code does not execute on Server Side

You may use node-jsdom (https://www.npmjs.com/package/node-jsdom) if you really need to use window or document object. Just install

$ npm install node-jsdom 

Here (https://github.com/darrylwest/node-jsdom) you will get help on node-jsdom

Place your window. related code inside componentDidMount function.

In Index.html or Index.cshtml

Change From

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

To

<app asp-ng2-prerender-module="ClientApp/dist/main-server">Loading...</app>

If you are using angular4 in aspnetcore, It should work fine

Related