Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to listen for component resize events within an Angular2 component?

Tags:

angular

I'm writing an Angular2 component that needs to dynamically change its content when resized. I am using the experimental Renderer in @angular/core (v2.1.0) and can wire up a click listener with the following:

this.rollupListener = this.renderer.listen(this.rollUp, 'click', (event) => {
  ...
});

But unfortunately I cannot do the same for a resize event - both 'resize' or 'onresize' do not work:

this.resizeListener = this.renderer.listen(this.container, 'resize', (event) => {
  // this never fires :(
});

I am able to pick up on browser resize events using the following:

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

But unfortunately not all component resizing in my application is due to a browser resize.

Basically, I'm looking for the JQuery equivalent of:

$(this.container).resize(() => {
  ...
});
like image 899
Michael McGowan Avatar asked Nov 24 '16 00:11

Michael McGowan


4 Answers

I ended up implementing a service that uses the element-resize-detector library (https://github.com/wnr/element-resize-detector). Couldn't find a TypeScript definition file but with a little help (Use element-resize-detector library in an Angular2 application), implemented the following:

element-resize-detector.d.ts

declare function elementResizeDetectorMaker(options?: elementResizeDetectorMaker.ErdmOptions): elementResizeDetectorMaker.Erd;

declare namespace elementResizeDetectorMaker {
    interface ErdmOptions {
        strategy?: 'scroll' | 'object';
    }

    interface Erd {
        listenTo(element: HTMLElement, callback: (elem: HTMLElement) => void);
        removeListener(element: HTMLElement, callback: (elem: HTMLElement) => void);
        removeAllListeners(element: HTMLElement);
        uninstall(element: HTMLElement);
    }
}

export = elementResizeDetectorMaker;

resize.service.ts

import { Injectable } from '@angular/core';
import * as elementResizeDetectorMaker from 'element-resize-detector';

@Injectable()
export class ResizeService {
  private resizeDetector: any;

  constructor() {
    this.resizeDetector = elementResizeDetectorMaker({ strategy: 'scroll' });
  }

  addResizeEventListener(element: HTMLElement, handler: Function) {
    this.resizeDetector.listenTo(element, handler);
  }

  removeResizeEventListener(element: HTMLElement) {
    this.resizeDetector.uninstall(element);
  }
}

my-component.ts

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

@Component({
  selector: 'my-component',
  template: ``
})
export class MyComponent {
  constructor(private el: ElementRef, private resizeService: ResizeService) {
  }

  ngOnInit() {
    this.resizeService.addResizeEventListener(this.el.nativeElement, (elem) => {
      // some resize event code...
    });
  }

  ngOnDestroy() {
    this.resizeService.removeResizeEventListener(this.el.nativeElement);
  }
}
like image 101
Michael McGowan Avatar answered Oct 17 '22 09:10

Michael McGowan


This angular 7 library does a pretty good job: https://www.npmjs.com/package/angular-resize-event

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

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

// Import the resized event model
import { ResizedEvent } from 'angular-resize-event';

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

  onResized(event: ResizedEvent) {
    this.width = event.newWidth;
    this.height = event.newHeight;
  }
}
like image 28
Ulises Torelli Avatar answered Oct 17 '22 08:10

Ulises Torelli


I wrote this Angular2 directive to solve this.

You can install it by npm install bound-sensor. The advantage of using this method is it tells you once the size of parent of component changes and it doesn't depend on window resize! Imagine you need to expand and refresh your content base on size of its parent, this solves it easily.

like image 39
PRAISER Avatar answered Oct 17 '22 09:10

PRAISER


As an alternative in order to be able to listen to a specific container that is resizing we can use (window:resize)="onResize($event)" in html and in component in the method onResize(event: UIEvent) you can do whatever you want on resize.

like image 35
Andrei Chivu Avatar answered Oct 17 '22 09:10

Andrei Chivu