0

I need to apply some custom styling on an element based on the window's current screenWidth.

That's successfully done by using the following @HostListener:

 @HostListener('window:resize', ['$event'])
  public resize() {

   // apply styles here depending on current window.innerWidth...

  }

However, I want to trigger the resize method ONLY when window's width has changed and do nothing when height has changed.

The way it is so far, the resize method is also called if the user changes the window height and that is breaking my styling logic!

So my question is: Is there a way in Angular to make something like ('window:resizeX') in order to call resize() only when window width changes, ignoring changes on window height?

4
  • 1
    I guess the best way of doing it is to store previous window width and compare it to new width inside resize function. something like private windowOldWidth: number = window.innerWidth and resize() { if(this.windowOldWidth === window.innerWidth) { return; } this.windowOldWidth = window.innerWidth; // rest of logic here } Commented Mar 8, 2021 at 15:38
  • Thanx for the insight. That successfully solved my issue! Commented Mar 8, 2021 at 15:42
  • 1
    why not use css media querys? Commented Nov 4, 2021 at 7:41
  • Indeed media queries are the overall go-to approach, but sometimes you need to do something with javascript in response to window changes. That's when media queries are not super great Commented Nov 4, 2021 at 14:25

3 Answers 3

7

You can use this method:

fromEvent(window, 'resize')
  .pipe(map(() => window.innerWidth), distinctUntilChanged())
  .subscribe(() => this.onResize());

and if you want some optimization then use auditTime():

fromEvent(window, 'resize')
  .pipe(auditTime(100), map(() => window.innerWidth), distinctUntilChanged())
  .subscribe(() => this.onResize());

so your method will run not often than every 100ms

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

Comments

4

The main common ways to listen to the resize are

  1. fromEvent(window, 'resize')
  2. @HostListener('window:resize', ['$event'])

both of them have some advantages over the other, mainly, it's all about preference and context.

Check this fromevent window vs hostlistener.

@Oleg gave the fix of your issue using fromEvent operator, If you need the fix using the HostListener way. it could be like that.

private lastScreenWidth;
....

ngAfterViewInit(){
    this.lastScreenWidth = window.innerWidth;
}

@HostListener('window:resize', ['$event'])
private resize(event) {
    if (event.target.innerWidth !== this.lastScreenWidth) {
        // Do your staff based on window width resize..
        this.lastScreenWidth = event.target.innerWidth;
    }
}

Comments

2

Oleg Postoev is right, that the best way to go.

This version only fires if the width is constant for a bit (800ms);

fromEvent(window, 'resize').pipe(
  debounceTime(800),
  tap((event: UIEvent) => {
    const width = event.target['innerWidth'];
    // DO SOMETHING
  }, takeUntil(this.unsubscribe$)) // CLEANUP
).subscribe();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.