2

Is it possible to listen for a window resize from a Angular6 service? I can do it from a component using:

 @HostListener('window:resize', ['$event'])
  onResize(event) {
    //perform actions
  }

This does not seem to be working for a service however.

5 Answers 5

2

In this case, you may subscribe to 'window:resize' in app.component and have a service which will handle all the data. Depends on what do you want to do with it.

just for example if you want just to store(and share) the window size you should have a service:

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

@Injectable() // could be @Injectable({ providedIn: 'root' }) in 6+ version
export class ResizeService {

  currentSize$: Subject<number|string> = new Subject<number|string>();

  getSize(): Observable<number|string> {
    return this.currentSize$.asObservable();
  }

  setSize(size: number|string): void {
   this.currentSize$.next(size);
  }

}

Then in your app.component.ts;

import { Component } from '@angular/core';
import { ResizeService } from '<path/to/service>';

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

  constructor(private resizeService: ResizeService) {}

  resizeHandler($event): void {
    this.resizeService.setSize($event.target.innerWidth);
  }
}

In any component that you want to get these values:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject, Observable } from 'rxjs'
import { takeUntil } from 'rxjs/operators';
import { ResizeService } from '<path/to/service>';

@Component({
  selector: 'app-my-component',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit, OnDestroy {

  private unsubscribeHelper$: Subject<void> = new Subject<void>();
  public size: number | string;     

  constructor(private resizeService: ResizeService) {}

  ngOnInit(): void {
    this.resizeService.getSize().pipe(takeUntil(this.unsubscribeHelper$))
      .subscribe((size: number | string) => this.size = size);
  }

  ngOnDestroy(): void {
    this.unsubscribeHelper$.next();
    this.unsubscribeHelper$.complete();
  }
}

So far this is the most universal solution to cover most of cases when you need to process data through the service and share it among the application

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer, was hoping for a pure service solution. But this does do the trick.
1

Hi you can attach to event manager in constructor and handle it in a function, all this can be in a service.

public appWidth: number = window.innerWidth; //default value
public appHeight: number = window.innerHeight; //default value

private OnResize(event: any) {
  this.appWidth = event.target.innerWidth;
  this.appHeight = event.target.innerHeight;
}

constructor(private eventManager: EventManager) {
  this.eventManager.addGlobalEventListener('window', 'resize', this.OnResize.bind(this));
}

1 Comment

This works really nicely. Maybe add _width: Subject<number> with pipe(distinctUntilChanged()) and some debounceTime becouse this event is firing like crazy :D
1

You can create an observable that listens to window resize in the service and listen to it from components.

In service file:

public resizeObservable$: Observable<boolean> = fromEvent(window, 'resize').pipe(map(_ => window.innerWidth < 480));

In Components file:

    this.appService.resizeObservable$.pipe(takeUntil(this.destroyNotifier$)).subscribe(x => {
      // do changes based on the info
      this.isMobile = x;
    });

Comments

1

Update for 2023, a complete Angular service that provides window resize events:

import {Injectable} from '@angular/core';
import {
  debounceTime,
  fromEvent,
  map, Observable,
  startWith,
} from 'rxjs';

export interface IWindowResize {
  width: number;
  height: number;
}

@Injectable({
  providedIn: 'root'
})
export class ResizeService {

  readonly $onResize: Observable<IWindowResize> = fromEvent(window, 'resize')
    .pipe(
      startWith(window), // to provide initial size event
      debounceTime(50), // to avoid producing events too fast
      map(() => ({width: window.innerWidth, height: window.innerHeight}))
    );
}

Unlike other answers here, it guarantees initial value, plus not to overload the client with resize events (they often emit way too fast). And, it is a complete solution.

Comments

0

@HostListener attaches a listener to the host element. it only will accept the keydown and keyup events.

so it's not possible to resize windows from HostListener

1 Comment

Nope that's wrong, it does listen to resize events.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.