therightdoctors
therightdoctors

Reputation: 548

ReferenceError: window is not defined , angular6 universal

I have an angular6 universal application, I am integrating ng-simple-slideshow for the image slider, it's building successful, but while running: npm run serve: SSR giving below error: please suggest some solution.thanks

ReferenceError: window is not defined
at F:\new_trd_back_up\dist\server.js:247023:8032
at vt (F:\new_trd_back_up\dist\server.js:246852:163)
at Object.module.exports (F:\new_trd_back_up\dist\server.js:246852:177)
at __webpack_require__ (F:\new_trd_back_up\dist\server.js:20:30)
at Object.jspdf (F:\new_trd_back_up\dist\server.js:87271:18)
at __webpack_require__ (F:\new_trd_back_up\dist\server.js:59361:30)
at Object../src/app/presentation/presentation.component.ts (F:\new_trd_back_up\dist\server.js:81159:13)
at __webpack_require__ (F:\new_trd_back_up\dist\server.js:59361:30)
at Object../src/app/presentation/presentation.component.ngfactory.js (F:\new_trd_back_up\dist\server.js:81046:11)
at __webpack_require__ (F:\new_trd_back_up\dist\server.js:59361:30)

Upvotes: 6

Views: 7670

Answers (3)

Remy
Remy

Reputation: 1093

Edit: This answer and question are wrong from the root, Angular uses Domino these days anyways and you should use Injection or Guards, for further explanation, read the manual.

This also can be solved by using Dominos.

Add this to 'server.ts':

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;

Ticket's issue and suggestion on Github

Upvotes: 3

Daniel Danielecki
Daniel Danielecki

Reputation: 10512

With NestJS you can it by simply applying the applyDomino, like so:

import { AngularUniversalModule, applyDomino } from '@nestjs/ng-universal';
import { join } from 'path';
import { Module } from '@nestjs/common';

// Get working directory of client bundle.
const BROWSER_DIR = join(process.cwd(), 'dist/apps/browser');

applyDomino(global, join(BROWSER_DIR, 'index.html')); // Mock document, window etc.

@Module({
  imports: [
    AngularUniversalModule.forRoot({
      bundle: require('./../functions/dist/apps/server/main'), // Bundle is created dynamically during build process.
      liveReload: true,
      viewsPath: BROWSER_DIR
    })
  ]
})
export class AppNestModule {}

Edit: after upgrading from Angular 8 to Angular 10 it stopped working, which you can realise based on #451. As of now, the raw domino has to be used in such a form (server.ts):

import { createWindow } from 'domino';
import { join } from 'path';
const indexHtml = join(
  process.cwd(),
  'dist/apps/browser/index2.html'
);
const win = createWindow(indexHtml);

// Polyfills
(global as any).window = win;
(global as any).document = win.document;
(global as any).navigator = win.navigator;

import { ApplicationModule } from './app.module'; // IMPORTANT: MUST be placed AFTER all the code above

More detailed answer #830 (comment).

Upvotes: 2

foram kantaria
foram kantaria

Reputation: 786

"window is not defined" came from 3rd party library which accessing window variable.

You should wrapping your code with browser check condition

HTML:

<ng-container *ngIf="isBrowser">
    <!-- In my case, ngx-siema & ngx-slcik -->
    <ngx-siema></ngx-siema> 
</ng-container>

TS:

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

isBrowser;

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

if (this.isBrowser) { 
  // put your code which is access window variable 
} 

A good example of usage could be found here.

Upvotes: 2

Related Questions