Angular window resize event

I would like to perform some tasks based on the window resize event (on loading and dynamic).

I currently have a DOM as follows:

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

Event triggers correctly

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

How to get width and height from this event object?

Thank.

+191
javascript angular
Feb 20 '16 at 18:42
source share
13 answers
 <div (window:resize)="onResize($event)" 
 onResize(event) { event.target.innerWidth; } 

or

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

Supported global targets: window , document and body .

Until https://github.com/angular/angular/issues/13248 is implemented in Angular, for performance it is better to subscribe to DOM events and use RXJS to reduce the number of events, as shown in some other answers.

+438
Feb 20 '16 at 19:17
source share

@ Günter answer is correct. I just wanted to suggest another method.

You can also add host @Component() inside @Component() -decorator. You can put the event and the desired function call in the host-metadata property as follows:

 @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 } } 
+58
01 Dec '16 at 11:48
source share

The proper way to do this is to use the EventManager class to bind the event. This allows your code to work on alternative platforms, such as server-side using Angular Universal.

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

Using in a component is as simple as adding this service as a provider to your application module, and then importing it into the component constructor.

 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(); } } } 
+39
May 7 '17 at 16:22
source share

I know this was asked a long time ago, but there is a better way to do it now! I'm not sure anyone will see this answer. Obviously your import:

 import { fromEvent } from "rxjs/observable/fromEvent"; import { Observable } from "rxjs/Observable"; import { Subscription } from "rxjs/Subscription"; 

Then in your component:

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

Then be sure to unsubscribe!

 ngOnDestroy() { this.resizeSubscription$.unsubscribe() } 
+30
Aug 22 '18 at 14:33
source share

Here is the best way to do this. Based on Birovsky’s answer .

Step 1. Create an angular service using RxJS 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 }; }; 

Step 2: Add the above service and subscribe to any of the Observables created in the service, where you would like to receive a window resize event.

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

A good understanding of reactive programming will always help overcome complex problems. Hope this helps someone.

+29
Jan 07 '17 at 5:58 on
source share

I have not seen anyone talking about MediaMatcher angular/cdk .

You can define MediaQuery and attach a listener to it - then anywhere in your template (or ts) you can call things if Matcher matches. 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; } 

source: https://material.angular.io/components/sidenav/overview

+10
Feb 17 '18 at 13:44
source share

Assuming that <600px means mobile for you, you can use this observable and subscribe to it:

First we need the current window size. Thus, we create an observable that emits only one value: the current window size.

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

Then we need to create another observable so that we know when the window was resized. For this we can use the "fromEvent" operator. To learn more about rxjs operators, visit: rxjs

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

Collapse these two threads to get our observable:

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

Now you can subscribe to it as follows:

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

Do not forget to unsubscribe :)

+6
May 7 '17 at 17:34
source share

Based on @cgatian's solution, I would suggest the following simplification:

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

Using:

 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) { } } 
+3
Dec 10 '17 at 13:48 on
source share

This is not exactly the answer to the question, but it can help someone who needs to determine the resizing for any item.

I created a library that adds a resized event to any element - an angular resize event .

It internally uses a ResizeSensor from CSS element requests .

Usage example

HTML

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

Typescript

 @Component({...}) class MyComponent { width: number; height: number; onResized(event: ResizedEvent): void { this.width = event.newWidth; this.height = event.newHeight; } } 
+3
Jan 15 '18 at 11:34
source share

I wrote this library to find once resizing a section border (resizing) in Angular, maybe this will help other people. You can put it in the root component, do the same as resizing the window.

Step 1: Import Module

 import { BoundSensorModule } from 'angular-bound-sensor'; @NgModule({ (...) imports: [ BoundSensorModule, ], }) export class AppModule { } 

Step 2: Add a directive as shown below

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

Step 3: Get Border Size Information

 import { HostListener } from '@angular/core'; @Component({ selector: 'simple-component' (...) }) class SimpleComponent { @HostListener('resize', ['$event']) onResize(event) { console.log(event.detail); } } 
+2
Aug 15 '17 at 13:09 on
source share

In Angular2 (2.1.0), I use ngZone to capture a screen change event.

Take a look at an example:

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

I hope this help!

+1
Mar 03 '17 at 7:10
source share

The code below allows you to observe any resize for any given div in Angular.

 <div #observed-div> </div> 

then in the component:

 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; } 
0
Nov 28 '18 at 11:43
source share

There is a ViewportRuler service in corner CDKs. It works outside the zone and also works with server-side rendering.

0
Jul 21 '19 at 9:08
source share



All Articles