Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get style of DOM elements in Angular?

Tags:

angular

I know you can use ngStyle to set styles of an element. But how do I get styles of an element (ie, the default styles as rendered by the browser)?

This code doesn't work but expresses what I'm trying to do:

<p>TEXT</p>
width of TEXT element is {{textElement.width}}
height of TEXT element is {{textElement.height}}

I want the p element to render normally (however the browser wants to, without telling it a width or height). However, I want to know what the rendered width and height are. How do I bind things to capture this?

EDIT: Some people asked what I want to do with the width and height. What I want to do is something like this:

<p *ngIf="!isEditing">{{myText}}</p>
<textarea *ngIf="isEditing" [(ngModel)]="myText"></textarea>

By default, p is displayed and textarea is not. If the user enters editing mode, p gets replaced by textarea. I wanted to set textarea's width and height to match p's so the transition looks seamless. Is there a better way to do this?

like image 402
Ray Zhang Avatar asked May 19 '17 05:05

Ray Zhang


2 Answers

The best way is to use a directive through which you can get access to the native DOM element to which this directive is applied. Then you can wait until the DOM is rendered in AfterViewInit hook and use getComputedStyle method to get all computed styles.

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

@Directive({
  selector: '[style-getter]'
})

export class StyleGetter {
  constructor(public el: ElementRef) {}

  ngOnChanges() {
    setTimeout(() => {
      console.log(this.el.nativeElement.offsetWidth);
    })
  }

  ngAfterViewInit() {
    console.log(this.el.nativeElement.offsetWidth);
  }
}

You also should probably hook into ngOnChanges hook since often DOM is re-rendered when input bindings change. You can use setTimeout to wait until all styles are computed and DOM is rendered.

You also have to use offsetWidth instead of width, because:

offsetWidth returns computed element's width, while el.style.width just returns width property defined in element.style by javascript and does not reflect real element's dimensions.

Read more here.

like image 104
Max Koretskyi Avatar answered Oct 05 '22 23:10

Max Koretskyi


this can also be done using @ViewChild

stackblitz link: https://stackblitz.com/edit/angular-playground-jzgein

component.ts:

import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'my-app',
  styleUrls: ['./app.component.scss'],
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
   @ViewChild('viewChildHook', {static: true}) viewChildHook: ElementRef;

ngOnInit(){
      const value = getComputedStyle(this.viewChildHook.nativeElement).getPropertyValue('--my-variable-name');
      console.log("value", value);

}

}

component.html:

<div #viewChildHook class="html-dom-element">
    aaaaaaaaaaaaaaaaaaaaaa
    bbbbbbbbbbbbbbbbbbbbbb
    cccccccccccccccccccccc
</div>

component.scss:

.html-dom-element{
  --my-variable-name: 300px;
    width: var(--my-variable-name);
}
like image 35
omer Avatar answered Oct 05 '22 23:10

omer