I have component like below which is basically a popover:
import {Component, Input, ViewChild} from 'angular2/core'
declare var $: any;
@Component({
selector: 'popover',
template: `
<div id="temp" [ngStyle]="{'position':'absolute', 'z-index':'10000', 'top': y + 'px', left: x + 'px'}"
[hidden]="hidden" #temp>
<ng-content></ng-content>
</div>
`
})
export class Popover {
@ViewChild("temp") temp;
private hidden: boolean = true;
private y: number = 0;
private x: number = 0;
show(target, shiftx = 0, shifty = 0){
let position = $(target).offset();
this.x = position.left + shiftx;
this.y = position.top + shifty;
this.hidden = false;
console.log("#temp", this.temp.nativeElement.getBoundingClientRect()); //all 0s
console.log("temp id", document.getElementById('temp').getBoundingClientRect()); //all 0s
}
hide(){
this.hidden = true;
}
}
Inside the show()
method I am trying to get the result of getBoundingClientRect()
but its returning 0
for all properties but when I type in document.getElementById("temp").getBoundingClientRect()
from Chrome's console I get proper result with actual values in the properties. Why the difference and what can I do to get the actual value from my component?
Instead of using setTimeout or lifecycle hooks that can be triggered more than once, I solved it with setting the Renderer to watch the window load event.
import { OnInit, Renderer2} from '@angular/core';
...
export class MyComponent implements OnInit {
constructor(private el: ElementRef, private render: Renderer2) {}
ngOnInit() {
this.render.listen('window', 'load', () => {
const rect = this.el.nativeElement.getBoundingClientRect().top;
})
}
}
Maybe this helps someone's usecase.
For some reason, the DOM was not updated right after it was shown so, a setTimeout
e.g. 10 did the trick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With