Element height and width change detection in Angular 2

Edit: Modern answer

Modern browsers support the ResizeObserver API. The API has been out for a number of years and is now widely supported. Unfortunately, Edge only supports it now that it's on Chromium. If that matters to you, look at the old answer or use a polyfill.

If you're interested, here goes. You want to create a ResizeObserver object and call observe on it. In this example, the blue block keeps resizing as we cycle the text and padding. The current size of the element is added to the unordered list.

const btn = document.getElementById('btn');
const container = document.getElementById('container');
const output = document.getElementById('output');
btn.onclick = () => {
  if (index > 2) {
    if (container.className === '') {
      container.className = 'high';
    } else {
      container.className = '';
    }
    index = 0;
  }
  container.innerText = values[index++];
}

let index = 0;
const values = [
  'Short',
  'Longer text',
  'Very much longer text of the kind that will fill a large container',
];

function createEntry(text) {
const li = document.createElement('li');
    li.innerText = text;
    output.appendChild(li);
}

let obs = new ResizeObserver(entries => {
  console.log(entries)
  for (let entry of entries) {
    const cr = entry.contentRect;
    createEntry(`Element size: ${cr.width}px x ${cr.height}px`)
  }
});
obs.observe(container);
#container {
  display: inline-block;
  background: lightblue;
}
.high {
  padding: 1rem;
}
<div>
  <button id="btn">Cycle</button>
</div>
<div id="container">Test This</div>
<ul id="output">
</ul>

Original answer

The problem is not even an Angular problem. More generally, how do you detect size changes in any element other than window? There is an onresize event, but this is only triggered for window and there are no other obvious solutions.

The general way that many approach this, is to set an interval of, say, 100ms and check the width and height of the div to detect a change. As horrible as it sounds, this is the most common approach.

From this answer to the more general question, there is a library to do this using only events: http://marcj.github.io/css-element-queries/. Supposedly, it's quite good. You would use the ResizeSensor to get what you're looking for.

Unless of course, you're only expecting the div to resize when the window does. Then onresize is what you're looking for.


Detecting a change in any element of the angular component. We can use a ResizeObserver (class from import ResizeObserver from 'resize-observer-polyfill'; ) without library.

here is my implementation:

Import:

import ResizeObserver from 'resize-observer-polyfill';

Implementation:

@ViewChild('divId') //eg: <div #divId><div> 
public agNote: ElementRef; //Element Reference on which the callback needs to be added

/**
   * this will bind resize observer to the target element
   */
  elementObserver() {
    var ro = new ResizeObserver(entries => {
      for (let entry of entries) {
        const cr = entry.contentRect;
        console.log('Element:', entry.target);
        console.log(`Element size: ${cr.width}px x ${cr.height}px`);
        console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
        console.log($event);

      }
    });

    // Element for which to observe height and width 
    ro.observe(this.agNote.nativeElement);
  }

For angular users, You can easily apply this code....

Html

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

Angular

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

Remember you have to install node module and import it to your app.module.ts file.

Check this link for more: https://www.npmjs.com/package/angular-resize-event

Tags:

Angular