How to inject window into a service?
This is working for me currently (2018-03, angular 5.2 with AoT, tested in angular-cli and a custom webpack build):
First, create an injectable service that provides a reference to window:
import { Injectable } from '@angular/core';// This interface is optional, showing how you can add strong typings for custom globals.// Just use "Window" as the type if you don't have custom global stuffexport interface ICustomWindow extends Window { __custom_global_stuff: string;}function getWindow (): any { return window;}@Injectable()export class WindowRefService { get nativeWindow (): ICustomWindow { return getWindow(); }}
Now, register that service with your root AppModule so it can be injected everywhere:
import { WindowRefService } from './window-ref.service';@NgModule({ providers: [ WindowRefService ], ...})export class AppModule {}
and then later on where you need to inject window
:
import { Component} from '@angular/core';import { WindowRefService, ICustomWindow } from './window-ref.service';@Component({ ... })export default class MyCoolComponent { private _window: ICustomWindow; constructor ( windowRef: WindowRefService ) { this._window = windowRef.nativeWindow; } public doThing (): void { let foo = this._window.XMLHttpRequest; let bar = this._window.__custom_global_stuff; }...
You may also wish to add nativeDocument
and other globals to this service in a similar way if you use these in your application.
edit:Updated with Truchainz suggestion.edit2:Updated for angular 2.1.2edit3:Added AoT notesedit4:Adding any
type workaround noteedit5: Updated solution to use a WindowRefService which fixes an error I was getting when using previous solution with a different buildedit6: adding example custom Window typing
With the release of angular 2.0.0-rc.5 NgModule was introduced. The previous solution stopped working for me. This is what I did to fix it:
app.module.ts:
@NgModule({ providers: [ { provide: 'Window', useValue: window } ], declarations: [...], imports: [...]})export class AppModule {}
In some component:
import { Component, Inject } from '@angular/core';@Component({...})export class MyComponent { constructor (@Inject('Window') window: Window) {}}
You could also use an OpaqueToken instead of the string 'Window'
Edit:
The AppModule is used to bootstrap your application in main.ts like this:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModule } from './app/app.module';platformBrowserDynamic().bootstrapModule(AppModule)
For more information about NgModule read the Angular 2 documentation: https://angular.io/docs/ts/latest/guide/ngmodule.html
You can get window from injected document.
import { Inject } from '@angular/core';import { DOCUMENT } from '@angular/common';export class MyClass { private window: Window; constructor(@Inject(DOCUMENT) private document: Document) { this.window = this.document.defaultView; } check() { console.log(this.document); console.log(this.window); }}