How to get width of (DOM) Element in Angular2

Kevin Regenrek picture Kevin Regenrek · Aug 22, 2016 · Viewed 70.5k times · Source

there a some similiar threads but I couldn't find a suitable answer for my needs. So that direct DOM access should be strictly avoided in angular2 I'm just wondering whats best practice for this.

What I wan't to achieve is a resize of a element based on the current width.

workitemresize.component.ts

import { Directive, ElementRef, HostListener, Renderer, Input } from '@angular/core';

@Directive({
  selector: '[workItemResize]'
})

export class WorkItemResizeDirective implements ngAfterViewInit {

  private el: HTMLElement;
  private renderer: Renderer;

  constructor(el: ElementRef, public renderer: Renderer)
  { 
    this.el = el.nativeElement; 
    this.renderer = renderer;
  }  


  @HostListener('window:resize', ['$event.target']) 
  onResize() 
  { 
    this.resizeWorks();
  }

  ngAfterViewInit() {
    this.resizeWorks();
  }

  private resizeWorks(): void {
    this.renderer.setElementStyle(this.el, 'height', this.el.width); // <-- doesn't work I kow that this.el.width doesn't exist but just for demonstration purpose
    this.renderer.setElementStyle(this.el, 'height', '500'); // <-- works
  }

}

projects.template.html

<div class="posts row">
        <div class="work-item col-xs-12 col-sm-6 col-no-padding"  workItemResize *ngFor="let post of posts">

                <!-- show some fancy image -->
                <div class="img"  [ngStyle]="{'background-image':'url('+post.better_featured_image.source_url+')'}"></div>

        </div>
</div>

Related: https://github.com/angular/angular/issues/6515

Answer

G&#252;nter Z&#246;chbauer picture Günter Zöchbauer · Aug 22, 2016

I don't know a way to get the width from the host element without accessing nativeElement but setting could be done like:

@HostListener('window:resize', ['$event.target']) 
onResize() { 
  this.resizeWorks();
}

@HostBinding('style.height.px')
elHeight:number;

private resizeWorks(): void {
  this.elHeight = this.el.nativeElement.width;
}

If you can add an element inside your components template like

<div style="width: 100%;" #div (window:resize)="elHeight = div.getBoundingClientRect()">
  <!-- your template here -->
</div>

then this would work without direct DOM access at all (but not after init).