I have created an Angular 2 app which contains a component whose HTML element I am trying to position relative to that of another component. In order to compute the exact coordinates, I need to know my own element's width and height as rendered by the browser.
I am using window.getComputedStyle(this.elementRef.nativeElement)
to get those properties. I noticed that, as the page is being rendered, the properties keep changing until the page rendering has finished. In order to get informed about any changes and adjust the positioning, I check the values in a ngAfterViewChecked
method of my component.
However, it seems ngAfterViewChecked
is not called when the rendering leads to new computed style properties, as I found that my hook is not called any more, even though the computed style properties are still changing. I assume that the Angular framework is not designed to detect such a change.
My first attempt was to implement the ngDoCheck
hook, but it seems this one isn't called either after some time and before the computed style property has its final value. I assume that I do not yet fully understand when exactly this hook is intended to be called.
I finally found out that, if I implement a setTimeout
function in ngAfterViewChecked
, this leads to this same hook being called again later, even if I pass only a dummy function like:
setTimeout(() => {}, 500);
But frankly, I do not understand why this so. Can someone please explain to me the connection between the setTimeout
and the ngAfterViewChecked
hook?
And while this occurs to be a somewhat dirty work-around: What is the proper 'Angular' way to detect and handle a change in computed style attributes?
Code excerpt:
export class MyComponent implements OnInit, AfterViewChecked
{
private cssWidth: number;
private cssHeight: number;
constructor(private elementRef: ElementRef, private renderer: Renderer2)
{
}
ngAfterViewChecked()
{
console.log("ngAfterViewChecked");
this.updateView();
}
public updateView()
{
const sizeX = parseFloat(window.getComputedStyle(this.elementRef.nativeElement).width) || 0;
const sizeY = parseFloat(window.getComputedStyle(this.elementRef.nativeElement.height) || 0;
if (sizeX === this.cssWidth && sizeY === this.cssHeight) {
// no change
return;
}
console.log("Change detected!");
// TODO Does not work without this dummy timeout function (else no more changes detected) - why so??
setTimeout(() => {}, 500);
[.. doing the positioning here ..]
}