কীভাবে একটি পরিষেবাতে উইন্ডো ইনজেক্ট করবেন?


111

আমি টাইপস্ক্রিপ্টে একটি কৌনিক 2 পরিষেবা লিখছি যা ব্যবহার করবে localstorage। আমি windowআমার সেবার ব্রাউজারের অবজেক্টের একটি রেফারেন্স ইনজেকশন করতে চাই যেহেতু আমি Angular 1.x এর মতো কোনও বৈশ্বিক পরিবর্তনশীল উল্লেখ করতে চাই না $window

আমি কেমন করে ঐটি করি?

উত্তর:


135

এটি বর্তমানে আমার জন্য কাজ করছে (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();
    }
}

এখন, সেই পরিষেবাটি আপনার মূল অ্যাপমোডুলের সাথে নিবন্ধ করুন যাতে এটি সর্বত্র ইনজেকশনের ব্যবস্থা করতে পারে:

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যদি এই অ্যাপ্লিকেশনটিতে এগুলি ব্যবহার করেন তবে আপনি এই পরিষেবাটিতে একইভাবে এবং অন্যান্য গ্লোবালগুলি যুক্ত করতে ইচ্ছুক হতে পারেন ।


সম্পাদনা: ট্রুচাইঞ্জ পরামর্শ সহ আপডেট হয়েছে। সম্পাদনা 2: কৌণিক 2.1.2 সম্পাদনার জন্য আপডেট হয়েছে: যুক্ত করা হয়েছে এওটি নোটগুলি সম্পাদনা 4: anyপ্রকারের ওয়ার্ক্রাউন্ড নোট এডিট 5 যুক্ত করা হচ্ছে : একটি উইন্ডোআরফ সার্ভিস ব্যবহারের জন্য আপডেট সমাধান যা একটি ভিন্ন বিল্ড সম্পাদনা 6 সহ পূর্ববর্তী সমাধানটি ব্যবহার করার সময় আমার যে ত্রুটিটি পেয়েছিল তা সংশোধন করে: উদাহরণটি যুক্ত করে কাস্টম উইন্ডো টাইপ করা হচ্ছে


1
কনস্ট্রাক্টর পরামিতিগুলিতে @ ইন্জেক্ট থাকা আমার জন্য ত্রুটিগুলির একগুচ্ছ ছুঁড়ে ফেলেছে যেমন ORIGINAL EXCEPTION: No provider for Window!। তবে এটি অপসারণ আমার জন্য সমস্যাটি স্থির করে। প্রথম দুটি বৈশ্বিক লাইন ব্যবহার করা আমার পক্ষে যথেষ্ট ছিল।
ট্রাইউনমড

আকর্ষণীয় ^^ আমাকে আরও কয়েকটি ডেমো প্রকল্পে এটি ব্যবহার করতে হবে - @Injectআমি No provider for Windowত্রুটি না পেয়ে । ম্যানুয়ালটির দরকার নেই এটি বেশ সুন্দর @Inject!
এলউইন



2
@ ব্রায়ান হ্যাঁ, এটি এখনও অ্যাক্সেস করছে windowতবে এর মধ্যে পরিষেবাটি windowইউনিট পরীক্ষায় নেটিভ স্টাফগুলিকে আটকানোর অনুমতি দেয় এবং এসএসআর-র হিসাবে আপনি উল্লেখ করেছেন একটি বিকল্প পরিষেবা দেওয়া যেতে পারে যা সার্ভারের জন্য একটি মক / নুপ উইন্ডো প্রকাশ করে। অ্যাঙ্গিটার আপডেট হওয়ার সাথে সাথে আমি এওটিটি যে কারণে উল্লেখ করেছি তা মোড়ক উইন্ডো ভেঙে যাওয়ার প্রাথমিক সমাধানগুলির বেশ কয়েকটি।
এলওয়াইন

34

কৌণিক মুক্তির সাথে 2.0.0-rc.5 এনজিএমডুল চালু হয়েছিল। পূর্ববর্তী সমাধানটি আমার পক্ষে কাজ করা বন্ধ করে দিয়েছে। এটি ঠিক করার জন্য আমি এটিই করেছি:

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) {}
}

'উইন্ডো' স্ট্রিংয়ের পরিবর্তে আপনি ওপেক টোকেনও ব্যবহার করতে পারেন

সম্পাদনা:

অ্যাপমোডুলটি আপনার অ্যাপ্লিকেশনটিকে মূল.স্টে বুটস্ট্র্যাপ করতে ব্যবহৃত হয়:

import { platformBrowserDynamic  } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule)

এনজিমডুল সম্পর্কে আরও তথ্যের জন্য কৌণিক 2 ডকুমেন্টেশন পড়ুন: https://angular.io/docs/ts/latest/guide/ngmodule.html


19

আপনি সরবরাহকারী সেট করার পরে আপনি কেবল এটি ইনজেকশন করতে পারেন:

import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);

constructor(private window: Window) {
    // this.window
}

তবে আমি যখন window.varপৃষ্ঠার সামগ্রী পরিবর্তন করি তখন পরিবর্তন হয় না
রবীন্দ্র পায়েল 12'16

6
উইন্ডো ইনজেক্টেবল না হওয়ায় এটি সাফারিটিতে কাজ করেনি। আমাকে নিজের ইনজেকশনযোগ্য টাইপ তৈরি করতে হয়েছিল যাতে আমার প্রয়োজনীয় উইন্ডোর বৈশিষ্ট্য রয়েছে। অন্যান্য
উত্তরে

এই পদ্ধতির কাজ হয় না, কারণ ব্যবহারভ্যালু প্রকৃতপক্ষে আপনি যে মানটি সরবরাহ করেছেন তার একটি অনুলিপি তৈরি করে। দেখুন: github.com/angular/angular/issues/10788#issuecomment-300614425 । আপনি যদি এটিকে ব্যবহারকারখানার জন্য ব্যবহার করতে এবং কলব্যাক থেকে মানটি ফিরিয়ে দেন তবে এই পদ্ধতির কাজ হবে work
লেভি লিন্ডসে

18

আপনি ইনজেকশন ডকুমেন্ট থেকে উইন্ডো পেতে পারেন।

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);
  }

}

15

এটি কৌনিক ২.১.১ এ কাজ করার জন্য আমাকে @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 }

10

কৌণিক আরসি 4 এ নিম্নলিখিত কাজগুলি যা উপরের কয়েকটি উত্তরের সংমিশ্রণ, আপনার মূল অ্যাপ্লিকেশনগুলিতে এটি সরবরাহকারীদের যুক্ত করে:

@Component({
    templateUrl: 'build/app.html',
    providers: [
        anotherProvider,
        { provide: Window, useValue: window }
    ]
})

তারপরে আপনার পরিষেবা ইত্যাদিতে এটি কনস্ট্রাক্টারে ইনজেক্ট করুন

constructor(
      @Inject(Window) private _window: Window,
)

10

@ কম্পোনেন্ট ঘোষণার আগে আপনি এটিও করতে পারেন,

declare var window: any;

সংকলকটি আসলে আপনাকে এখন গ্লোবাল উইন্ডো ভেরিয়েবল অ্যাক্সেস করতে দেবে যেহেতু আপনি এটিকে যে কোনও প্রকারের সাথে ধরে নেওয়া গ্লোবাল ভেরিয়েবল হিসাবে ঘোষণা করেন।

আমি আপনার অ্যাপ্লিকেশনটির যেকোন জায়গায় উইন্ডো অ্যাক্সেস করার পরামর্শ দেব না, যদিও আপনার প্রয়োজনীয় উইন্ডো বৈশিষ্ট্যগুলি অ্যাক্সেস / সংশোধনকারী পরিষেবাগুলি তৈরি করা উচিত (এবং আপনার উপাদানগুলিতে সেই পরিষেবাগুলি ইনজেক্ট করুন) আপনি উইন্ডোটি কী কী করতে পারেন তা পরিবর্তন করার অনুমতি না দিয়ে স্কোপ করার জন্য create পুরো উইন্ডো অবজেক্ট।


আপনি যদি সার্ভার-সাইড রেন্ডারিং করেন তবে আপনার কোডটি নষ্ট হয়ে যাবে s কারণ শ্রাবক-সাইডে আপনার কোনও উইন্ডো অবজেক্ট নেই, এবং আপনার নিজের ইনজেকশন প্রয়োজন need
অ্যালেক্স নিকুলিন

9

আমি উইন্ডো স্ট্রিংয়ের জন্য ওপাক টোকেন ব্যবহার করেছি :

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 কৌণিক 2.0.0-rc-4 এ বুটস্ট্র্যাপে হয়েছিল।

তবে Angular 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 {}

6

আজকের (এপ্রিল ২০১)) হিসাবে পূর্ববর্তী সমাধানের কোডটি কাজ করে না, আমি মনে করি অ্যাপ্লিকেশনগুলিতে সরাসরি উইন্ডোটি ইনজেক্ট করা সম্ভব এবং তারপরে অ্যাপ্লিকেশনটিতে বিশ্বব্যাপী অ্যাক্সেসের জন্য আপনার প্রয়োজনীয় মানগুলি সংগ্রহ করা সম্ভব, তবে আপনি যদি নিজের নিজস্ব পরিষেবা তৈরি এবং ইনজেকশন করতে পছন্দ করেন তবে একটি উপায় সহজ সমাধান এটি।

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;
    }
}

6

কৌণিক 4 InjectToken পরিচয় করিয়ে, এবং তারা ডকুমেন্ট নামক একটি টোকেন তৈরি DOCUMENT । আমি মনে করি এটি সরকারী সমাধান এবং এটিটি এটিতে কাজ করে।

এনজিএক্স-উইন্ডো-টোকেন নামে একটি ছোট লাইব্রেরি তৈরি করতে আমি একই যুক্তিটি ব্যবহার করি এবং এটি বার বার করা বন্ধ করে দিতে।

আমি এটিকে অন্য প্রকল্পে ব্যবহার করেছি এবং সমস্যা ছাড়াই এওটিতে তৈরি করেছি।

অন্যান্য প্যাকেজে আমি এটি কীভাবে ব্যবহার করেছি তা এখানে

এখানে নিমজ্জনকারী

আপনার মডিউল মধ্যে

imports: [ BrowserModule, WindowTokenModule ] আপনার উপাদান

constructor(@Inject(WINDOW) _window) { }




4

বিল্ট-ইন টোকেন 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;
        }
    });

1
সুতরাং, আমি এটি আমার সরবরাহকারী ফোল্ডারে রেখেছি (উদাহরণস্বরূপ) এবং তারপরে আমি আমার উপাদানটির নির্মাতাকে এই ইঞ্জেকশন টোকেনটি ব্যবহার করব? @Inject(WINDOW) private _window: anyএবং এটি কৌনিক দ্বারা সরবরাহ করা ডকুমেন্ট ইনজেকশন টোকেনের মতো ব্যবহার করবেন?
স্পার্কার 73

হ্যাঁ, এটুকুই আছে।
জলপোলা

হা. এটি পুরোপুরি কাজ করে, এই সাধারণ সমাধানের জন্য ট্যাঙ্কগুলি।
স্পার্কার 73

3

আমি জানি যে প্রশ্নটি কীভাবে উইন্ডো অবজেক্টটিকে কোনও উপাদানতে ইনজেক্ট করা যায় তবে আপনি কেবল স্থানীয় স্টোরারেজে যাওয়ার জন্য এটি করছেন seems যদি আপনি সত্যিকার অর্থে লোকাল স্টোরেজ চান, তবে কেন এই পরিষেবাটি ব্যবহার করবেন না যা এইচ 5 ওয়েস্টস্টোরেজের মতোই প্রকাশ করে । তারপরে আপনি উপাদানটি এর আসল নির্ভরতাগুলি বর্ণনা করবে যা আপনার কোডটিকে আরও পঠনযোগ্য করে তোলে।


2
যদিও এই লিঙ্কটি প্রশ্নের উত্তর দিতে পারে, উত্তরের প্রয়োজনীয় অংশগুলি এখানে অন্তর্ভুক্ত করা এবং রেফারেন্সের জন্য লিঙ্কটি সরবরাহ করা ভাল। লিঙ্কযুক্ত উত্তর পরিবর্তিত হলে লিঙ্কযুক্ত উত্তরগুলি অবৈধ হতে পারে।
সমস্ত কর্মী

3

এটি সবচেয়ে সংক্ষিপ্ত / পরিষ্কার উত্তর যা আমি কৌণিক 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);
  }
}

2

আপনি কৌণিক 4 তে এনজিউন ব্যবহার করতে পারেন:

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

constructor(private zone: NgZone) {}

print() {
    this.zone.runOutsideAngular(() => window.print());
}

2

এটি 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
);

0

@ ম্যাক্সিসাম এনজিএক্স-উইন্ডো-টোকেনের জন্য ধন্যবাদ । আমি অনুরূপ কিছু করছিলাম তবে আপনার কাছে চলে এসেছি। উইন্ডো পুনরায় আকারের ইভেন্টগুলি শোনার এবং গ্রাহকদের অবহিত করার জন্য এটি আমার পরিষেবা।

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});
}

সংক্ষিপ্ত এবং মিষ্টি এবং একটি কবজ মত কাজ করে।


0

গ্লোবাল ভেরিয়েবলগুলি যখন অ্যাপ্লিকেশন জুড়ে অ্যাক্সেসযোগ্য হয় তখন ডিআই (ডিপেন্ডেন্সি ইনজেকশন) এর মাধ্যমে উইন্ডো অবজেক্ট পাওয়া ভাল ধারণা নয়।

আপনি যদি উইন্ডো অবজেক্টটি ব্যবহার করতে না চান তবে আপনি selfকীওয়ার্ডটিও ব্যবহার করতে পারেন যা উইন্ডো অবজেক্টটিকেও নির্দেশ করে।


3
এটা ভাল পরামর্শ না। নির্ভরতা ইনজেকশন ক্লাস (উপাদান, নির্দেশাবলী, পরিষেবাগুলি, পাইপস, ...) পরীক্ষা করা সহজ করে তোলে (উদাহরণস্বরূপ এমনকি ব্রাউজার ছাড়াও) এবং সার্ভার-সাইড রেন্ডারিং বা ওয়েব ওয়ার্কার্সের মতো বিভিন্ন প্ল্যাটফর্মগুলিতে পুনরায় ব্যবহার করা সহজ। এটি কারও পক্ষে কাজ করতে পারে এবং সরলতার জন্য কিছু আবেদন থাকতে পারে, তবে ডিআই ব্যবহার করে নিরুৎসাহিত করা একটি খারাপ উত্তর H
গন্টার জ্যাচবাউয়ার

আপনি যদি সার্ভার-সাইড রেন্ডারিং করেন তবে আপনার কোডটি নষ্ট হয়ে যাবে s কারণ শ্রাবক-সাইডে আপনার কোনও উইন্ডো অবজেক্ট নেই, এবং আপনার নিজের ইনজেকশন প্রয়োজন।
অ্যালেক্স নিকুলিন

-1

ভাবলেন!

export class HeroesComponent implements OnInit {
  heroes: Hero[];
  window = window;
}

<div>{{window.Object.entries({ foo: 1 }) | json}}</div>

আপনি যদি সার্ভার-সাইড রেন্ডারিং করেন তবে আপনার কোডটি নষ্ট হয়ে যাবে s কারণ শ্রাবক-সাইডে আপনার কোনও উইন্ডো অবজেক্ট নেই, এবং আপনার নিজের ইনজেকশন প্রয়োজন।
অ্যালেক্স নিকুলিন

-2

আসলে এখানে উইন্ডো অবজেক্টটি অ্যাক্সেস করা খুব সহজ আমার মূল উপাদান এবং আমি এটির কার্যকারিতাটি পরীক্ষা করেছি

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 );
  }

}

আপনি যদি সার্ভার-সাইড রেন্ডারিং করেন তবে আপনার কোডটি নষ্ট হয়ে যাবে s কারণ শ্রাবক-সাইডে আপনার কোনও উইন্ডো অবজেক্ট নেই, এবং আপনার নিজের ইনজেকশন প্রয়োজন।
অ্যালেক্স নিকুলিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.