कोणीय खिड़की आकार घटना


232

मैं विंडो री-साइज़ इवेंट (लोड पर और गतिशील रूप से) के आधार पर कुछ कार्य करना चाहूंगा।

वर्तमान में मेरे पास मेरा DOM इस प्रकार है:

<div id="Harbour">
    <div id="Port" (window:resize)="onResize($event)" >
        <router-outlet></router-outlet>
    </div>
</div>

घटना सही ढंग से आग

export class AppComponent {
   onResize(event) {
        console.log(event);
    }
}

मैं इस ईवेंट ऑब्जेक्ट से चौड़ाई और ऊँचाई कैसे प्राप्त करूं?

धन्यवाद।


6
वास्तव में एक कोणीय प्रश्न नहीं है। खिड़की की वस्तु को देखो । आप इसे पा सकते हैं innerHeightऔर innerWidthगुण ..
सक्साका

1
@ सक्सा सही है, आपको बस करने की ज़रूरत हैconsole.log(event.target.innerWidth )
पंकज पारकर

इस जानकारी के लिए धन्यवाद, सक्साका / पंकज - मुझे यकीन नहीं था कि यह सिर्फ एक सादे जावास्क्रिप्ट चीज़ या एक टाइपस्क्रिप्ट चीज़ या एक कोणीय घटना है। मैं यहां अपने लिए एक बहुत ही कठिन सीखने की अवस्था पर चढ़ रहा हूं और आपके इनपुट की सराहना करता हूं।
DanAbdn

जवाबों:


525
<div (window:resize)="onResize($event)"
onResize(event) {
  event.target.innerWidth;
}

या HostListener डेकोरेटर का उपयोग कर :

@HostListener('window:resize', ['$event'])
onResize(event) {
  event.target.innerWidth;
}

समर्थित वैश्विक लक्ष्य हैं window,document और body

जब तक https://github.com/angular/angular/issues/13248 को कोणीय में लागू किया जाता है, तब तक प्रदर्शन के लिए बेहतर है कि डोम ईवेंट को अनिवार्य रूप से सब्सक्राइब करें और कुछ अन्य उत्तरों में दिखाए अनुसार घटनाओं की मात्रा को कम करने के लिए RXJS का उपयोग करें।


15
क्या आपके द्वारा उपयोग किए जाने वाले वाक्यविन्यास के बारे में कोई दस्तावेज है: खिड़की: आकार ?
क्लेमेंट

3
बिल्कुल सही। आप उपयोग कर सकते हैं document, windowऔर body github.com/angular/angular/blob/…
Günter Zöchbauer

5
सही उत्तर .. मेरा मानना ​​है कि @HostListener क्लीनर तरीका है :) लेकिन HostListener को पहली बार उपयोग करके आयात करना सुनिश्चित करेंimport { Component, OnInit, HostListener } from '@angular/core';
गौरव शर्मा

4
त्वरित टिप: यदि आप पहले लोड पर भी ट्रिगर करना चाहते हैं, तो ngAfterViewInit को @ कोणीय / कोर से लागू करें। angular.io/api/core/AfterViewInit
Zymotik

6
हालाँकि, जो लोग जानना चाहते हैं कि डेब्यू टाइम के साथ HostListener कैसे काम करता है, नीचे दिए गए लिंक का पालन करें plnkr.co/edit/3J0dcDaLTJBxkzo8Akyg?p=preview
jcdsr

65

@ गुंटर का जवाब सही है। मैं अभी एक और तरीका प्रस्तावित करना चाहता था।

आप @Component()-decorator के अंदर होस्ट-बाइंडिंग भी जोड़ सकते हैं । आप होस्ट-मेटाडेटा-प्रॉपर्टी में ईवेंट और वांछित फंक्शन कॉल डाल सकते हैं, जैसे:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  host: {
    '(window:resize)': 'onResize($event)'
  }
})
export class AppComponent{
   onResize(event){
     event.target.innerWidth; // window width
   }
}

2
मैंने इस पृष्ठ पर प्रत्येक विधि की कोशिश की है और ऐसा लगता है कि उनमें से कोई भी काम नहीं करता है। क्या इस बारे में कोई आधिकारिक दस्तावेज है।
टमाटर

लोड पर व्यूपोर्ट की ऊँचाई कैसे प्राप्त की जाती है?
गिरिधर कार्णिक

@GiridharKarnik, क्या आपने window.innerWidthअंदर ngOnInit, या ngAfterViewInitतरीकों को करने की कोशिश की है ?
जॉन

@ टोमेटो एपीआई-संदर्भ यहां पाया जा सकता है संदर्भ के कई संदर्भ ऑटोगेनेरेटेड हैं (मुझे लगता है), और उदाहरणों या विस्तृत विवरण की कमी है। कुछ एपीआई-संदर्भों में बहुत सारे उदाहरण हैं। हालाँकि मुझे इस बारे में डॉक्स से कोई ठोस उदाहरण नहीं मिला। शायद यह कहीं छिपा हुआ है: पी
जॉन

1
यहाँ इसका उपयोग कैसे किया जाता है, इसका एक संदर्भ है
आनंद रॉकज़

52

मुझे पता है कि यह एक लंबे समय से पहले पूछा गया था, लेकिन अब ऐसा करने का एक बेहतर तरीका है! मुझे यकीन नहीं है कि कोई भी इस जवाब को देखेंगे। जाहिर है आपके आयात:

import { fromEvent, Observable, Subscription } from "rxjs";

फिर अपने घटक में:

resizeObservable$: Observable<Event>
resizeSubscription$: Subscription

ngOnInit() {
    this.resizeObservable$ = fromEvent(window, 'resize')
    this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
      console.log('event: ', evt)
    })
}

तब नष्ट करने के लिए सदस्यता समाप्त करने के लिए सुनिश्चित हो!

ngOnDestroy() {
    this.resizeSubscription$.unsubscribe()
}

मेरे लिए काम करने का एकमात्र तरीका। धन्यवाद!! :-) ... मुझे अभी आपका आयात समायोजित करना था। शायद मेरा rxjs नया है:import { fromEvent, Observable,Subscription } from "rxjs";
Jette

इसमें मैं डेब्यू (1000) कहां जोड़ सकता हूं?
दीपक

3
देर से जवाब के लिए क्षमा करें: बहस जोड़ने के लिए, आप का उपयोग करना चाहते हैंthis.resizeSubscription$ = this.resizeObservable$.pipe(debounceTime(1000)).subscribe( evt => { console.log('event: ', evt) })
क्रिस स्टेनली

41

ऐसा करने का सही तरीका इवेंट को बांधने के लिए EventManager वर्ग का उपयोग करना है । यह आपके कोड को वैकल्पिक प्लेटफार्मों में काम करने की अनुमति देता है, उदाहरण के लिए सर्वर पक्ष के साथ कोणीय यूनिवर्सल।

import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Injectable } from '@angular/core';

@Injectable()
export class ResizeService {

  get onResize$(): Observable<Window> {
    return this.resizeSubject.asObservable();
  }

  private resizeSubject: Subject<Window>;

  constructor(private eventManager: EventManager) {
    this.resizeSubject = new Subject();
    this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
  }

  private onResize(event: UIEvent) {
    this.resizeSubject.next(<Window>event.target);
  }
}

एक घटक में उपयोग इस सेवा को आपके app.module के लिए एक प्रदाता के रूप में जोड़ने के रूप में सरल है और फिर इसे एक घटक के निर्माता में आयात करना है।

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'my-component',
  template: ``,
  styles: [``]
})
export class MyComponent implements OnInit {

  private resizeSubscription: Subscription;

  constructor(private resizeService: ResizeService) { }

  ngOnInit() {
    this.resizeSubscription = this.resizeService.onResize$
      .subscribe(size => console.log(size));
  }

  ngOnDestroy() {
    if (this.resizeSubscription) {
      this.resizeSubscription.unsubscribe();
    }
  }
}

जहाँ तक मैं बता सकता हूँ, यह कभी मोबाइल पर फायर नहीं करता है। इस दृष्टिकोण के साथ आपको प्रारंभिक विंडो आकार कैसे मिलता है?
user3170530

मोबाइल में windowऑब्जेक्ट नहीं होता है , ठीक वैसे ही जैसे सर्वर में नहीं होता है window। Im विभिन्न मोबाइल कॉन्फ़िगरेशन से परिचित नहीं है, लेकिन आपको आसानी से उपरोक्त कोड को सही वैश्विक ईवेंट श्रोता से बाँधने में सक्षम होना चाहिए
cgatian

@cgatian मैं एक noob हूँ लेकिन यह सही उत्तर की तरह लगता है। दुर्भाग्य से मैं घटक में मेरी सदस्यता लॉग बनाने के लिए कोई किस्मत नहीं कर रहा हूँ। क्या आप इस जवाब को जोड़ सकते हैं कि घटक में यह कैसे सदस्यता लें ताकि कोई अपडेट देख सके?
मैथ्यू हरवुड

@ cgatian मैं एक प्लंकर बनाऊंगा लेकिन यह काम नहीं कर रहा था। सेवा में फिल्टर अजीब लगता है stackoverflow.com/q/46397531/1191635
मैथ्यू हरवुड

3
@cgatian Mobile does not have a window object.... आपको क्यों लगता है कि मोबाइल ब्राउज़र में विंडो ऑब्जेक्ट नहीं है?
ड्रेनै

31

यहाँ यह करने के लिए एक बेहतर तरीका है। बायरोव्स्की के उत्तर के आधार पर ।

चरण 1: एक बनाएं angular serviceRxJS साथ observables

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';

@Injectable()
export class WindowService {
    height$: Observable<number>;
    //create more Observables as and when needed for various properties
    hello: string = "Hello";
    constructor() {
        let windowSize$ = new BehaviorSubject(getWindowSize());

        this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();

        Observable.fromEvent(window, 'resize')
            .map(getWindowSize)
            .subscribe(windowSize$);
    }

}

function getWindowSize() {
    return {
        height: window.innerHeight
        //you can sense other parameters here
    };
};

चरण 2: उपरोक्त को हटा दें serviceऔर Observablesसेवा के भीतर बनाई गई किसी भी चीज़ की सदस्यता लें , जहाँ भी आपको विंडो आकार परिवर्तन की घटना प्राप्त होगी।

import { Component } from '@angular/core';
//import service
import { WindowService } from '../Services/window.service';

@Component({
    selector: 'pm-app',
    templateUrl: './componentTemplates/app.component.html',
    providers: [WindowService]
})
export class AppComponent { 

    constructor(private windowService: WindowService) {

        //subscribe to the window resize event
        windowService.height$.subscribe((value:any) => {
            //Do whatever you want with the value.
            //You can also subscribe to other observables of the service
        });
    }

}

प्रतिक्रियाशील प्रोग्रामिंग की एक ध्वनि समझ हमेशा कठिन समस्याओं पर काबू पाने में मदद करेगी। आशा है कि यह किसी की मदद करता है।


मेरा मानना ​​है कि यह एक त्रुटि है: यह। $ = (विंडोब्लेड $ .pluck ('ऊंचाई') को ऑब्जर्वेबल <संख्या>) के रूप में। ऐसा लगता है कि आप एक अलग पंक्ति में दो बार चिपके हुए हैं () पंक्ति में दो बार
ज्यूरियल

मैं तुम्हें नहीं मिला, कृपया खुश रहो।
गिरिधर कार्णिक

परिवर्तन का पता लगाने के लिए निकाल दिया जाएगा क्योंकि आप इस घटना को कोणीय के बाहर कर रहे हैं, विश्वास है कि वह क्या मतलब है।
मार्क पीज़्ज़क - ट्रिलोन।

1
मुझे यह कहते हुए एक त्रुटि हुई कि 'प्लक' का व्यवहार BehaviorSubject पर मौजूद नहीं है। इस कोड को कोड में बदलना। इसके लिए $ = windowSize $ .map (x => x.height) ने मेरे लिए काम किया।
मैट सग्गुन

@GiridharKamik क्या आप एक ऐसा समाधान प्रदान कर सकते हैं, जो एक ही समय में चौड़ाई और ऊँचाई पर सदस्यता लेगा, जिसे हम दोनों चौड़ाई, ऊँचाई में 1 साधारण सदस्यता दे सकते हैं
ghiscoding

11

मैंने किसी को भी इस बारे MediaMatcherमें बात करते नहीं देखा angular/cdk

आप एक MediaQuery को परिभाषित कर सकते हैं और एक श्रोता को इसके साथ जोड़ सकते हैं - फिर अपने टेम्पलेट (या ts) पर कहीं भी आप मिलान करने वाले सामान का मिलान कर सकते हैं। LiveExample

App.Component.ts

import {Component, ChangeDetectorRef} from '@angular/core';
import {MediaMatcher} from '@angular/cdk/layout';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  mobileQuery: MediaQueryList;

  constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
    this.mobileQuery = media.matchMedia('(max-width: 600px)');
    this._mobileQueryListener = () => changeDetectorRef.detectChanges();
    this.mobileQuery.addListener(this._mobileQueryListener);
  }

  private _mobileQueryListener: () => void;

  ngOnDestroy() {
    this.mobileQuery.removeListener(this._mobileQueryListener);
  }

}

App.Component.Html

<div [class]="mobileQuery.matches ? 'text-red' : 'text-blue'"> I turn red on mobile mode 
</div>

App.Component.css

.text-red { 
   color: red;
}

.text-blue {
   color: blue;
}

स्रोत: https://material.angular.io/compenders/sidenav/overview


6

यह मानते हुए कि <600px का अर्थ आपके लिए मोबाइल है, आप इस अवलोकन योग्य का उपयोग कर सकते हैं और इसकी सदस्यता ले सकते हैं:

पहले हमें वर्तमान विंडो आकार की आवश्यकता है। इसलिए हम एक अवलोकनीय बनाते हैं जो केवल एक मान का उत्सर्जन करता है: वर्तमान विंडो का आकार।

initial$ = Observable.of(window.innerWidth > 599 ? false : true);

फिर हमें एक और अवलोकनीय बनाने की जरूरत है, ताकि हमें पता चले कि खिड़की का आकार कब बदला गया था। इसके लिए हम "FromEvent" ऑपरेटर का उपयोग कर सकते हैं। Rxjs के संचालकों के बारे में अधिक जानने के लिए कृपया देखें: rxjs

resize$ = Observable.fromEvent(window, 'resize').map((event: any) => {
  return event.target.innerWidth > 599 ? false : true;
 });

हमारे अवलोकन योग्य प्राप्त करने के लिए इन दो धाराओं को मिलाएं:

mobile$ = Observable.merge(this.resize$, this.initial$).distinctUntilChanged();

अब आप इसे इस तरह से सब्सक्राइब कर सकते हैं:

mobile$.subscribe((event) => { console.log(event); });

सदस्यता समाप्त करने के लिए याद रखें :)


5

वहाँ कोणीय CDK में एक ViewportRuler सेवा है। यह ज़ोन के बाहर चलता है, और सर्वर साइड रेंडरिंग के साथ भी काम करता है।


2
यह स्वीकृत उत्तर होना चाहिए। क्या सब कुछ आवश्यक है + यह कोणीय सीडीके इनबिल्ट कार्यक्षमता है।
डेनिस एम।

3

@Cgatian के समाधान के आधार पर मैं निम्नलिखित सरलीकरण का सुझाव दूंगा:

import { EventManager } from '@angular/platform-browser';
import { Injectable, EventEmitter } from '@angular/core';

@Injectable()
export class ResizeService {

  public onResize$ = new EventEmitter<{ width: number; height: number; }>();

  constructor(eventManager: EventManager) {
    eventManager.addGlobalEventListener('window', 'resize',
      e => this.onResize$.emit({
        width: e.target.innerWidth,
        height: e.target.innerHeight
      }));
  }
}

उपयोग:

import { Component } from '@angular/core';
import { ResizeService } from './resize-service';

@Component({
  selector: 'my-component',
  template: `{{ rs.onResize$ | async | json }}`
})
export class MyComponent {
  constructor(private rs: ResizeService) { }
}

मैंने इसे सबसे अच्छा समाधान के रूप में पाया, हालांकि, यह केवल तभी काम करता है जब विंडो को आकार दिया जाता है, लेकिन जब लोड नहीं होता है या जब राउटर बदलता है। क्या आप जानते हैं, राउटर चेंज, रीलोड या लोड के साथ आवेदन कैसे करें?
jcdsr

आप सेवा में एक फ़ंक्शन जोड़ सकते हैं और घटक @jcdsr में इसे ट्रिगर कर सकते हैं: getScreenSize () {this.onResize $ .emit ({चौड़ाई: window.innerWidth, height: window.innerHeight}); }
डैनियलॉव

3

यह सवाल के लिए बिल्कुल जवाब नहीं है लेकिन यह किसी ऐसे व्यक्ति की मदद कर सकता है जिसे किसी भी तत्व पर आकार में बदलाव का पता लगाने की आवश्यकता है।

मैंने एक पुस्तकालय बनाया है जो resizedकिसी भी तत्व में घटना जोड़ता है - कोणीय आकार घटना

यह आंतरिक रूप से उपयोग करता ResizeSensorहै CSS Element Queries

उदाहरण उपयोग

एचटीएमएल

<div (resized)="onResized($event)"></div>

टाइपप्रति

@Component({...})
class MyComponent {
  width: number;
  height: number;

  onResized(event: ResizedEvent): void {
    this.width = event.newWidth;
    this.height = event.newHeight;
  }
}

यदि आप विंडो का पता लगाना चाहते हैं तो कोणीय सामग्री ब्रेकपॉइंट ऑब्जर्वर पहले से ही सामग्री
डैरेन स्ट्रीट

लेकिन यह केवल विंडोज़ आकार का पता नहीं लगाता है, लेकिन किसी भी तत्व का आकार बदलता है।
मार्टिन वोल्क

2

मैंने एक बार अंगुली में घटक सीमा आकार परिवर्तन (आकार) खोजने के लिए यह काम लिखा है , क्या यह अन्य लोगों की मदद कर सकता है। आप इसे रूट कंपोनेंट पर रख सकते हैं, विंडो रिसाइज के समान काम करेंगे।

चरण 1: मॉड्यूल आयात करें

import { BoundSensorModule } from 'angular-bound-sensor';

@NgModule({
  (...)
  imports: [
    BoundSensorModule,
  ],
})
export class AppModule { }

चरण 2: नीचे की तरह निर्देश जोड़ें

<simple-component boundSensor></simple-component>

चरण 3: सीमा आकार विवरण प्राप्त करें

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

@Component({
  selector: 'simple-component'
  (...)
})
class SimpleComponent {
  @HostListener('resize', ['$event'])
  onResize(event) {
    console.log(event.detail);
  }
}

1

Angular2 (2.1.0) पर मैं स्क्रीन चेंज ईवेंट को कैप्चर करने के लिए ngZone का उपयोग करता हूं।

उदाहरण पर एक नज़र डालें:

import { Component, NgZone } from '@angular/core';//import ngZone library
...
//capture screen changed inside constructor
constructor(private ngZone: NgZone) {
    window.onresize = (e) =>
    {
        ngZone.run(() => {
            console.log(window.innerWidth);
            console.log(window.innerHeight);
        });
    };
}

मुझे उम्मीद है कि इस मदद!


1

नीचे दिए गए कोड से कोणीय में किसी भी दिए गए डिव के लिए किसी भी आकार में परिवर्तन का निरीक्षण किया जा सकता है।

<div #observed-div>
</div>

तब घटक में:

oldWidth = 0;
oldHeight = 0;

@ViewChild('observed-div') myDiv: ElementRef;
ngAfterViewChecked() {
  const newWidth = this.myDiv.nativeElement.offsetWidth;
  const newHeight = this.myDiv.nativeElement.offsetHeight;
  if (this.oldWidth !== newWidth || this.oldHeight !== newHeight)
    console.log('resized!');

  this.oldWidth = newWidth;
  this.oldHeight = newHeight;
}

मैं अधिकतम-चौड़ाई 767px पर काउंटर = 6 से काउंट = 0 तक एक परिवर्तन करना चाहता हूं, मैं यह कैसे करूं?
थानवीर शाह

0

सभी समाधान सर्वर-साइड या कोणीय सार्वभौमिक के साथ काम नहीं कर रहे हैं


0

मैंने इनमें से अधिकांश उत्तरों की जाँच की। फिर लेआउट पर कोणीय प्रलेखन की जाँच करने का निर्णय लिया ।

विभिन्न आकारों का पता लगाने के लिए कोणीय का अपना प्रेक्षक होता है और घटक या सेवा में इसे लागू करना आसान होता है।

एक सरल उदाहरण होगा:

import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';

@Component({...})
class MyComponent {
  constructor(breakpointObserver: BreakpointObserver) {
    breakpointObserver.observe([
      Breakpoints.HandsetLandscape,
      Breakpoints.HandsetPortrait
    ]).subscribe(result => {
      if (result.matches) {
        this.activateHandsetLayout();
      }
    });
  }
}

आशा करता हूँ की ये काम करेगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.