2

I'm working on an Angular 8 app, and we use global styles. I'm using the D3 chart library in the app and to set a style, you have to configure it in code. For example:

plottingArea.append('text')
    .attr('fill', '#00B2B3');

This will change the color of the text used in the D3 graph (svg). But since we use global styles, I need to find a way to pull this value into code so that if the style changes at some point, I won't have to change the code.

I tried creating a class selector and adding the color there, then adding the class to the html element that's being used for the chart (in this case, a div), then using @ViewChild to query for the class to get the color property value:

component.scss

.my-color {
  color: global-style('text', 'grey');
}

component.html

<div #my-div class="my-color"></div>

component.ts

@ViewChild('my-div', { static: false }) myDiv!: ElementRef;

ngAfterViewInit() {
  
  //this returns empty string
  const color = this.myDiv.nativeElement.style.color;

  //this returns null
  const style = this.myDiv.nativeElement.querySelector('.my-color');

}

So since I can't access the color value like that, I'm not sure how to do it.

u84six
  • 4,604
  • 6
  • 38
  • 65

4 Answers4

2

You can use getComputedStyle:

const color = window.getComputedStyle(this.myDiv.nativeElement).color;
0

If you are having issues getting the style with window.getComputedStyle, I think you may need to wait until the DOM is rendered in ngAfterViewInit, and check for changes to the DOM re-rendering in ngOnChanges

I think the best way would be to create a directive which can access the DOM.

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

export class ColorGetter {
  constructor(public el: ElementRef) {}
  ngOnChanges() {
    setTimeout(() => {
      console.log(this.el.nativeElement.style.color);
    })
  }
  ngAfterViewInit() {
    console.log(this.el.nativeElement.style.color);
  }
}

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.

Tore
  • 1,236
  • 2
  • 11
  • 21
  • 1
    Hmm, all that extra code just to get the value of a property? I suppose it's a security issue. Anyhow, I've tried ngAfterViewInit and I get the same empty string – u84six Feb 25 '21 at 21:11
0

This is what I ended up having to do:

component.scss

.my-color {
  fill: global-style('text', 'grey');
}

component.html

<div #my-div class="my-color"></div>

component.ts

plottingArea.append('text')
    .classed('my-color', true)

The classed() methods was the answer. But I'm still not sure why I wasn't able to get the value of a style.

u84six
  • 4,604
  • 6
  • 38
  • 65
0

I my codebase this is solved by using window.getComputedStyle() in ngAFterViewInit() event handle, but you have to delay getComputedStyle() call a bit. You can achieve it by wrapping the call in setTimeout(..., 1) function, like this:

public ngAfterViewInit(): void {
  setTimeout(() => {
    const color = window.getComputedStyle(someHtmlElement).color;
  }, 1);
}

I've noticed that timeout = 0 works in Firefox, but fails in Chrome. Thus I've set timeout to 1.

vlad2135
  • 1,556
  • 12
  • 14