जवाबों:
यह वर्तमान में मेरे लिए काम कर रहा है (2018-03, एओटी के साथ कोणीय 5.2, कोणीय-क्ली और एक कस्टम वेबपैक में परीक्षण किया गया):
सबसे पहले, एक इंजेक्टेबल सेवा बनाएं जो विंडो का संदर्भ प्रदान करती है:
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 stuff
export interface ICustomWindow extends Window {
__custom_global_stuff: string;
}
function getWindow (): any {
return window;
}
@Injectable()
export class WindowRefService {
get nativeWindow (): ICustomWindow {
return getWindow();
}
}
अब, अपने रूट AppModule के साथ उस सेवा को पंजीकृत करें ताकि इसे हर जगह इंजेक्ट किया जा सके:
import { WindowRefService } from './window-ref.service';
@NgModule({
providers: [
WindowRefService
],
...
})
export class AppModule {}
और फिर बाद में जहां आपको इंजेक्शन लगाने की आवश्यकता है 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;
}
...
nativeDocument
यदि आप अपने एप्लिकेशन में इनका उपयोग करते हैं तो आप इसी तरह से और अन्य ग्लोबल्स को भी इस सेवा में जोड़ना चाह सकते हैं ।
संपादित करें: ट्रूचेंज सुझाव के साथ अपडेट किया गया। edit2: कोणीय 2.1.2 के लिए अपडेट किया गया edit3: AoT नोट्स एडिट 4 जोड़ा गया: any
प्रकार वर्कअराउंड नोट edit5 को जोड़ना: एक WindowRefService का उपयोग करने के लिए अद्यतित समाधान जो एक त्रुटि को हल करता है जो मैं एक अलग बिल्ड edit6 के साथ पिछले समाधान का उपयोग करते समय प्राप्त कर रहा था: उदाहरण कस्टम विंडो टाइपिंग जोड़ना
@Inject
मुझे No provider for Window
त्रुटियां हुए। यह मैनुअल की जरूरत नहीं है बहुत अच्छा है @Inject
!
@Inject(Window)
काम करना था
window
, लेकिन बीच में सेवा के साथ यह window
यूनिट परीक्षणों में देशी सामान को बाहर निकालने की अनुमति देता है , और जैसा कि आप एसएसआर के लिए उल्लेख करते हैं, एक वैकल्पिक सेवा प्रदान की जा सकती है जो सर्वर के लिए एक नकली / नोज विंडो को उजागर करती है। एओटी का उल्लेख करने का कारण यह है कि कोणीय अद्यतन किए जाने पर एओटी में टूटी खिड़की को तोड़ने के लिए शुरुआती समाधानों में से कई हैं।
कोणीय 2.0.0-rc.5 के रिलीज के साथ NgModule पेश किया गया था। पिछले समाधान ने मेरे लिए काम करना बंद कर दिया। यह वही है जो मैंने इसे ठीक करने के लिए किया था:
app.module.ts:
@NgModule({
providers: [
{ provide: 'Window', useValue: window }
],
declarations: [...],
imports: [...]
})
export class AppModule {}
कुछ घटक में:
import { Component, Inject } from '@angular/core';
@Component({...})
export class MyComponent {
constructor (@Inject('Window') window: Window) {}
}
आप स्ट्रिंग 'विंडो' के बजाय एक OpaqueToken का उपयोग कर सकते हैं
संपादित करें:
AppModule का उपयोग इस तरह से main.ts में आपके एप्लिकेशन को बूटस्ट्रैप करने के लिए किया जाता है:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
NgModule के बारे में अधिक जानकारी के लिए कोणीय 2 प्रलेखन पढ़ें: https://angular.io/docs/ts/latest/guide/ngmodule.html
प्रदाता को सेट करने के बाद आप इसे इंजेक्ट कर सकते हैं:
import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);
constructor(private window: Window) {
// this.window
}
window.var
पृष्ठ की सामग्री को बदलता हूं तो उसमें बदलाव नहीं होता है
आप इंजेक्ट किए गए दस्तावेज़ से विंडो प्राप्त कर सकते हैं।
import { Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
export class MyClass {
constructor(@Inject(DOCUMENT) private document: Document) {
this.window = this.document.defaultView;
}
check() {
console.log(this.document);
console.log(this.window);
}
}
कोणीय 2.1.1 पर काम करने के लिए मुझे @Inject
एक स्ट्रिंग का उपयोग करके खिड़की करना था
constructor( @Inject('Window') private window: Window) { }
और फिर इसे इस तरह से मॉक करें
beforeEach(() => {
let windowMock: Window = <any>{ };
TestBed.configureTestingModule({
providers: [
ApiUriService,
{ provide: 'Window', useFactory: (() => { return windowMock; }) }
]
});
और साधारण में @NgModule
मैं इसे इस तरह प्रदान करता हूं
{ provide: 'Window', useValue: window }
कोणीय RC4 में निम्नलिखित कार्य जो आपके उपरोक्त app.ts में से कुछ के उत्तर का संयोजन है, इसे प्रदाता जोड़ते हैं:
@Component({
templateUrl: 'build/app.html',
providers: [
anotherProvider,
{ provide: Window, useValue: window }
]
})
फिर आपकी सेवा आदि में इसे कंस्ट्रक्टर में इंजेक्ट करें
constructor(
@Inject(Window) private _window: Window,
)
@Component घोषणा से पहले, आप भी ऐसा कर सकते हैं,
declare var window: any;
कंपाइलर वास्तव में आपको तब वैश्विक विंडो चर का उपयोग करने देगा, क्योंकि आप इसे किसी भी प्रकार के साथ एक वैश्विक वैश्विक चर घोषित करते हैं।
मैं आपके एप्लिकेशन में हर जगह विंडो एक्सेस करने का सुझाव नहीं दूंगा, लेकिन आपको ऐसी सेवाओं का निर्माण करना चाहिए जो आवश्यक विंडो विशेषताओं को एक्सेस / संशोधित करें (और अपने घटकों में उन सेवाओं को इंजेक्ट करें) जो आप उन्हें संशोधित करने की अनुमति दिए बिना विंडो के साथ कर सकते हैं। संपूर्ण विंडो ऑब्जेक्ट।
मैंने 'विंडो' स्ट्रिंग के लिए OpaqueToken का उपयोग किया :
import {unimplemented} from '@angular/core/src/facade/exceptions';
import {OpaqueToken, Provider} from '@angular/core/index';
function _window(): any {
return window;
}
export const WINDOW: OpaqueToken = new OpaqueToken('WindowToken');
export abstract class WindowRef {
get nativeWindow(): any {
return unimplemented();
}
}
export class BrowserWindowRef extends WindowRef {
constructor() {
super();
}
get nativeWindow(): any {
return _window();
}
}
export const WINDOW_PROVIDERS = [
new Provider(WindowRef, { useClass: BrowserWindowRef }),
new Provider(WINDOW, { useFactory: _window, deps: [] }),
];
और इसका इस्तेमाल सिर्फ WINDOW_PROVIDERS
Angular 2.0.0-rc-4 में बूटस्ट्रैप में आयात करने के लिए किया जाता है ।
लेकिन कोणीय 2.0.0-rc.5 की रिहाई के साथ मुझे एक अलग मॉड्यूल बनाने की आवश्यकता है:
import { NgModule } from '@angular/core';
import { WINDOW_PROVIDERS } from './window';
@NgModule({
providers: [WINDOW_PROVIDERS]
})
export class WindowModule { }
और सिर्फ मेरे मुख्य की आयात संपत्ति में परिभाषित किया गया है app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { WindowModule } from './other/window.module';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule, WindowModule ],
declarations: [ ... ],
providers: [ ... ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
आज (अप्रैल 2016) के अनुसार, पिछले समाधान में कोड काम नहीं करता है, मुझे लगता है कि विंडो को सीधे App.ts में इंजेक्ट करना संभव है और फिर उन मूल्यों को इकट्ठा करें जिनकी आपको ऐप में वैश्विक पहुंच के लिए सेवा में आवश्यकता है, लेकिन यदि आप अपनी स्वयं की सेवा बनाना और इंजेक्ट करना पसंद करते हैं, तो एक सरल तरीका यह है।
https://gist.github.com/WilldelaVega777/9afcbd6cc661f4107c2b74dd6090cebf
//--------------------------------------------------------------------------------------------------
// Imports Section:
//--------------------------------------------------------------------------------------------------
import {Injectable} from 'angular2/core'
import {window} from 'angular2/src/facade/browser';
//--------------------------------------------------------------------------------------------------
// Service Class:
//--------------------------------------------------------------------------------------------------
@Injectable()
export class WindowService
{
//----------------------------------------------------------------------------------------------
// Constructor Method Section:
//----------------------------------------------------------------------------------------------
constructor(){}
//----------------------------------------------------------------------------------------------
// Public Properties Section:
//----------------------------------------------------------------------------------------------
get nativeWindow() : Window
{
return window;
}
}
कोणीय 4 InjectToken पेश करते हैं, और वे भी दस्तावेज़ बुलाया के लिए एक टोकन बनाने डाक्यूमेंट । मुझे लगता है कि यह आधिकारिक समाधान है और यह एओटी में काम करता है।
मैं एक ही लॉजिक का उपयोग करता हूं, जिसे एक छोटी सी लाइब्रेरी बनाने के लिए कहा जाता है, जिसे ngx-window-token कहा जाता है ।
मैं इसे अन्य परियोजना में उपयोग किया है और मुद्दों के बिना एओटी में निर्माण।
यहां बताया गया है कि मैंने इसे दूसरे पैकेज में कैसे इस्तेमाल किया
यहां प्लंकर है
आपके मॉड्यूल में
imports: [ BrowserModule, WindowTokenModule ]
आपके घटक में
constructor(@Inject(WINDOW) _window) { }
यह करने के लिए पर्याप्त है
export class AppWindow extends Window {}
और करो
{ provide: 'AppWindow', useValue: window }
एओटी को खुश करने के लिए
दस्तावेज़ के माध्यम से खिड़की की वस्तु तक सीधी पहुंच का अवसर है
document.defaultView == window
यहाँ एक और उपाय है जो मैंने हाल ही में बनाया था, जब मैं बिल्ट-इन टोकेन defaultView
से थक गया DOCUMENT
और नल के लिए जाँच कर रहा था:
import {DOCUMENT} from '@angular/common';
import {inject, InjectionToken} from '@angular/core';
export const WINDOW = new InjectionToken<Window>(
'An abstraction over global window object',
{
factory: () => {
const {defaultView} = inject(DOCUMENT);
if (!defaultView) {
throw new Error('Window is not available');
}
return defaultView;
}
});
@Inject(WINDOW) private _window: any
और इसका उपयोग Angular द्वारा प्रदान किए गए DOCUMENT इंजेक्शन टोकन की तरह करें?
मुझे पता है कि सवाल यह है कि विंडो ऑब्जेक्ट को एक घटक में कैसे इंजेक्ट किया जाए, लेकिन आप ऐसा कर रहे हैं कि ऐसा लगता है कि लोकलस्टोरेज के लिए। यदि आप वास्तव में लोकलस्टोरेज चाहते हैं, तो उस सेवा का उपयोग क्यों न करें, जो h5webstorage की तरह ही उजागर होती है । फिर आप घटक इसकी वास्तविक निर्भरता का वर्णन करेंगे जो आपके कोड को अधिक पठनीय बनाता है।
यह सबसे छोटा / साफ जवाब है जो मैंने कोणीय 4 एओटी के साथ काम करते हुए पाया है
स्रोत: https://github.com/angular/angular/issues/12631#issuecomment-274260009
@Injectable()
export class WindowWrapper extends Window {}
export function getWindow() { return window; }
@NgModule({
...
providers: [
{provide: WindowWrapper, useFactory: getWindow}
]
...
})
export class AppModule {
constructor(w: WindowWrapper) {
console.log(w);
}
}
आप AngZ 4 पर NgZone का उपयोग कर सकते हैं:
import { NgZone } from '@angular/core';
constructor(private zone: NgZone) {}
print() {
this.zone.runOutsideAngular(() => window.print());
}
DOCUMENT
वैकल्पिक के रूप में चिह्नित करना भी एक अच्छा विचार है । प्रति कोणीय डॉक्स:
जब एप्लिकेशन और रेंडरिंग कॉन्टेक्ट्स एक जैसे नहीं होते हैं (जैसे कि वेब वर्कर में एप्लिकेशन को रन करते समय) एप्लिकेशन संदर्भ में दस्तावेज़ उपलब्ध नहीं हो सकता है।
यहां DOCUMENT
यह देखने का उपयोग करने का एक उदाहरण है कि क्या ब्राउज़र में एसवीजी समर्थन है:
import { Optional, Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common'
...
constructor(@Optional() @Inject(DOCUMENT) document: Document) {
this.supportsSvg = !!(
document &&
document.createElementNS &&
document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect
);
के लिए @maxisam धन्यवाद NGX खिड़की-टोकन । मैं भी कुछ ऐसा ही कर रहा था, लेकिन आपका स्विच ऑफ था। यह विंडो के आकार बदलने की घटनाओं और ग्राहकों को सूचित करने के लिए सुनने के लिए मेरी सेवा है।
import { Inject, Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { WINDOW } from 'ngx-window-token';
export interface WindowSize {
readonly width: number;
readonly height: number;
}
@Injectable()
export class WindowSizeService {
constructor( @Inject(WINDOW) private _window: any ) {
Observable.fromEvent(_window, 'resize')
.auditTime(100)
.map(event => <WindowSize>{width: event['currentTarget'].innerWidth, height: event['currentTarget'].innerHeight})
.subscribe((windowSize) => {
this.windowSizeChanged$.next(windowSize);
});
}
readonly windowSizeChanged$ = new BehaviorSubject<WindowSize>(<WindowSize>{width: this._window.innerWidth, height: this._window.innerHeight});
}
छोटा और मीठा और आकर्षण की तरह काम करता है।
DI के माध्यम से विंडो ऑब्जेक्ट प्राप्त करना (डिपेंडेंसी इंजेक्शन) एक अच्छा विचार नहीं है जब वैश्विक चर पूरे एप्लिकेशन तक पहुंच योग्य हों।
लेकिन अगर आप विंडो ऑब्जेक्ट का उपयोग नहीं करना चाहते हैं तो आप self
कीवर्ड का भी उपयोग कर सकते हैं जो विंडो ऑब्जेक्ट को भी इंगित करता है।
इसे सरल रखें, दोस्तों!
export class HeroesComponent implements OnInit {
heroes: Hero[];
window = window;
}
<div>{{window.Object.entries({ foo: 1 }) | json}}</div>
वास्तव में यहां विंडो ऑब्जेक्ट को एक्सेस करना बहुत ही सरल है, यह मेरा मूल घटक है और मैंने इसका परीक्षण किया है
import { Component, OnInit,Inject } from '@angular/core';
import {DOCUMENT} from '@angular/platform-browser';
@Component({
selector: 'app-verticalbanners',
templateUrl: './verticalbanners.component.html',
styleUrls: ['./verticalbanners.component.css']
})
export class VerticalbannersComponent implements OnInit {
constructor(){ }
ngOnInit() {
console.log(window.innerHeight );
}
}
ORIGINAL EXCEPTION: No provider for Window!
। हालांकि, इसे हटाने से मेरे लिए समस्या तय हो गई। सिर्फ पहली 2 वैश्विक लाइनों का उपयोग करना मेरे लिए पर्याप्त था।