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