28

I'm looking for a solution in Angular 4 to get the width of DOM element without taking any action (click or window resize), just after the page is loaded, but before I start to draw the svg. I've found a similar case in here but it doesn't work for me. I get the same error:

ERROR TypeError: Cannot read property 'nativeElement' of undefined

I need to get the width of div container to set veiwbox of svg I'm drawing inside it.

Here is the template:

<div id="what-is-the-width" class="svg-chart-container">
    <svg [innerHTML]="svg"></svg>
</div>

and TS file with stuff needed in this case:

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

export class SvgChartComponent implements OnInit {

  @ViewChild('what-is-the-width') elementView: ElementRef;

  constructor() { }

  ngAfterViewInit() {
    console.log(this.elementView.nativeElement);
  }

  ngOnInit() {
    //this method gets the data from the server and draw the svg
    this.getSVGChartData();
  }
}

Does anyone have ideas how to get this working?

mpro
  • 14,302
  • 5
  • 28
  • 43
  • It seems that "-" is not allowed in reference names, just have got `Uncaught Error: Template parse errors` – mpro Feb 09 '18 at 15:22

2 Answers2

54

You can't have the size of an element before the page is loaded. In case it's not clear enough, if the page isn't loaded, then your HTML element isn't loaded.

If you want to set the viewbox of your SVG according to a div, you will need to wait for the page to load, then change the viewbox. It's perfectly doable.

The fastest way of doing that is :

<div #container>Container's width is {{ container.offsetWidth }}</div>
<svg:svg [width]="container.offsetWidth"></svg>

I'll let you deal with the viewBox attribute, since I don't really know what you want to do with it.

You need to add the svg: prefix to tell angular it's not a custom directive, by the way.

  • Too simple! :) Thanks, it works! I'll edit the title and question because it is truly unclear. I've meant of course getting the width after the page load but before I fire method drawing the svg. – mpro Feb 09 '18 at 15:15
  • No problem ! Remember to mark your issue as resolved too ! –  Feb 09 '18 at 15:23
  • Oh, one more thing. How to pass this value from template to ts file? I need to use it in one more place. – mpro Feb 09 '18 at 15:36
  • 22
    `@ViewChild('container') container : ElementRef;` is the declaration. To get the value, it's `this.container.nativeElement.offsetWidth`. For your ide, you can use `(this.container.nativeElement as HTMLElement).offsetWidth`. –  Feb 09 '18 at 15:44
  • 1
    Oh, and you need to use the `nativeElement` after the init step of the life cycle hook. This means not in the constructor, but `ngOnInit` at least! –  Feb 09 '18 at 16:02
  • True that, when defined it before constructor it returned some error, so placed it into `ngOnInit()` – mpro Feb 09 '18 at 16:05
  • Doesn't work for me. I'm getting "Can't bind to 'width' since it isn't a known property of ':svg:svg" – sovemp Sep 29 '18 at 23:16
  • Then you did something wrong. Feel free to post a question with a [mcve] –  Sep 30 '18 at 00:24
  • 1
    If you get "Can't bind to 'width' since it isn't a known property of ':svg:svg" use: – J. Pinxten Dec 18 '18 at 16:46
  • Try to use "container.el.offsetWidth" instead if container.offsetWidth is undefined. – ntsd Mar 16 '20 at 05:15
  • Man... you did the trick easily and it worked like a charm! Thanks. – moreirapontocom Jan 04 '22 at 01:42
5

If anyone needs another solution:

<div id="element"></div>
const myElement = document.getElementById('element');

if(myElement){
  myElement.getBoundingClientRect().width; // Get the width of the your element
}