24

Some features in my component turn on or off depend on browser size, therefore I want to check browser width on resize event. However, I could do it using OnInit method. But I need to refresh browser when resize happened to update browser width

 ngOnInit() {
     if (window.innerWidth <= 767){
       ---- do something
      }
   }

I tried to use OnChanges method, but it does not work either.

OnChanges(changes:SimpleChanges){
console.log( 'width:====>' + changes[window.innerWidth].currentValue);
  if ( changes[window.innerWidth].currentValue <= 767 ){
      ---- do something
}

}

is there any suggestions or alternative way to accomplish this?

peterh
  • 11,875
  • 18
  • 85
  • 108
Kero
  • 1,924
  • 5
  • 33
  • 53

3 Answers3

43

You could just put handler on resize event over window object, but this will allow you to put only single resize event, latest registered event on onresize will work.

constructor(private ngZone:NgZone) {
    window.onresize = (e) =>
    {
        //ngZone.run will help to run change detection
        this.ngZone.run(() => {
            console.log("Width: " + window.innerWidth);
            console.log("Height: " + window.innerHeight);
        });
    };
}

To make it more angular way use @HostListener('window:resize') inside your component, which will allow to call your resize function(on which HostListner decorator has been mount) on resize of window.

@HostListener('window:resize', ['$event'])
onResize(event){
   console.log("Width: " + event.target.innerWidth);
}
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • This works on one component, but it doesn't work when I add it to another component. I suppose because the onresize event has already been defined. – S.. Jul 08 '17 at 11:49
  • 1
    `onresize` event can be registered on a window only once, if you try to register `onresize` event then the older will get discarded.. – Pankaj Parkar Jul 08 '17 at 11:55
  • 2
    Yes, thanks for clarifying. I went with the Host Listener solution, it allowed for multiple resize events (one in each component), and seems a 'more angular way' to do things, – S.. Jul 08 '17 at 19:54
  • 1
    @Sam you're correct, parden me. I updated an answer with more explanation. I should have updated this before. Thanks for heads up mate :) – Pankaj Parkar Jul 08 '17 at 20:08
  • i have angular app inside an iframe of a php web app. How do i make it work of the resize of the parent window. – Master Yoda Dec 07 '17 at 07:05
22

Use HostListener. You should probably debounce the resize event though before doing anything, it will fire everytime the size changes which could be dozens or hundreds of times in a few milliseconds as the user drags the window size.

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

@Component({...})
class TestComponent {
    @HostListener('window:resize')
    onWindowResize() {
        //debounce resize, wait for resize to finish before doing stuff
        if (this.resizeTimeout) {
            clearTimeout(this.resizeTimeout);
        }
        this.resizeTimeout = setTimeout((() => {
            console.log('Resize complete');
        }).bind(this), 500);
    }
}
Alex Egli
  • 1,884
  • 2
  • 24
  • 43
8

An easier way would be using the resize method on the html block that you want to detect:

<div class="some-class" (window:resize)="onResize($event)">...</div>

Then in your .ts file you can just add:

onResize(event) {

   const innerWidth = event.target.innerWidth;
   console.log(innerWidth);

   if (innerWidth <= 767) {
      ...do something
   }
}

Add this outside of the ngOnInit() {} unless you wanted the window size on page load.

When you resize your window, you'll see the console.log

Nosniw
  • 191
  • 2
  • 5
  • 1
    that's a very neat solution – Geek Jun 10 '18 at 20:37
  • This works for resizing the window, but not when the browser tab is dragged from one window to another of a different size. Is there a different `window:` to call for this? EDIT: Also, it doesn't change the size if you are double clicking the title bar to make it go full screen... – Robert Martin Aug 28 '19 at 20:04