24

I'm trying to implement a custom directive in Angular 2 for moving an arbitrary HTML element around. So far everything is working except that I don't now how to get the initial position of the HTML element when I click on it and want to start moving. I'm binding to the top and left styles of my HTML element with those two host bindings:

/** current Y position of the native element. */
@HostBinding('style.top.px') public positionTop: number;

/** current X position of the native element. */
@HostBinding('style.left.px') protected positionLeft: number;

The problem is that both of them are undefined at the beginning. I can only update the values which will also update the HTML element but I cannot read it? Is that suppose to be that way? And if yes what alternative do I have to retrieve the current position of the HTML element.

tzwickl
  • 1,341
  • 2
  • 15
  • 31

3 Answers3

32
<div (click)="move()">xxx</div>
// get the host element
constructor(elRef:ElementRef) {}

move(ref: ElementRef) {
  console.log(this.elRef.nativeElement.offsetLeft);
}

See also https://stackoverflow.com/a/39149560/217408

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • But offset doesn't give me the relative position of the element? – tzwickl Mar 03 '17 at 10:50
  • Your question doesn't say anything about "relative". `offsetLeft` is just an example. The rest is the same as in plain JavaScript, this is why I added the link to my answer. – Günter Zöchbauer Mar 03 '17 at 10:51
31

In typeScript you can get the position as follows:

@ViewChild('ElementRefName') element: ElementRef;

const {x, y} = this.element.nativeElement.getBoundingClientRect();
  • This solution won't work when the browser is not at 100% size – Loc Truong Oct 31 '19 at 05:05
  • 4
    What will work when the browser is not at 100% size? – SoEzPz Jun 22 '20 at 03:53
  • `@ViewChild('ElementRefName') element: ElementRef;` is an error now in Angular 13: error TS2564: Property 'element' has no initializer and is not definitely assigned in the constructor. – b264 May 06 '22 at 07:03
10

in html:

<div (click)="getPosition($event)">xxx</div>

in typescript:

getPosition(event){
    let offsetLeft = 0;
    let offsetTop = 0;

    let el = event.srcElement;

    while(el){
        offsetLeft += el.offsetLeft;
        offsetTop += el.offsetTop;
        el = el.parentElement;
    }
    return { offsetTop:offsetTop , offsetLeft:offsetLeft }
}
mohammad ali
  • 109
  • 1
  • 5
  • 4
    Testing this in an Angular app now and it's giving odd values (very high numbers). I don't believe a child's offset is the simple aggregation of all of it's parents offsets. I believe the correct property is offsetParent. – Rohan May 28 '19 at 03:04
  • 2
    @Rohan Yes, I'm using offsetParent instead of parentElement and it appears to be working. – C.M. Jul 01 '20 at 16:09