Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styles in component for D3.js do not show in angular 2

I am using Angular 2 and D3.js. I want to show a red rectangle.

It only works if I put styles in the style.css file. Check this plunkr

When I put my styles in the component styles: [], it does not work. Check this plunkr

How to let it work when I use the component styles: []? Thanks

UPDATE: @micronyks provides a solution, but it makes the styles in the component global, basically no difference with writing in style.css file. In this plunkr, it shows style in one component will override another component's styles, so cannot show green and red rectangles.

UPDATE 2: @Günter's way perfectly solve this problem!! Just a remind, for Günter's way: it needs at least Angular beta 10. (My other plunkrs use Angular beta 8) The working demo for green and one red rectangle using Angular beta 12 is here.

import {Component} from 'angular2/core' @Component({   selector: 'my-app',   providers: [],    styles: [`     /*this does not work*/     .bar {       fill: red;     }   `],   template: `     <div>       <svg class="chart"></svg>     </div>   `,   directives: [] }) export class App {   constructor() {}    ngOnInit() {     this.draw();   }    draw() {     let data = [{name: 'A', value: 1}];     let width = 400, height = 200;      let x = d3.scale.ordinal().rangeRoundBands([0, width]);     let y = d3.scale.linear().range([height, 0]);      let chart = d3.select(".chart")       .attr("width", width)       .attr("height", height)       .append("g");      x.domain(data.map(function(d) { return d.name; }));     y.domain([0, d3.max(data, function(d) { return d.value; })]);      chart.selectAll(".bar")       .data(data)       .enter().append("rect")       .attr("class", "bar")       .attr("x", function(d) { return x(d.name); })       .attr("y", function(d) { return y(d.value); })       .attr("height", function(d) { return height - y(d.value); })       .attr("width", x.rangeBand());   } } 
like image 422
Hongbo Miao Avatar asked Mar 25 '16 05:03

Hongbo Miao


People also ask

Does D3 js work with angular?

Getting data from a JSON APID3 natively supports JSON data, so it makes it really easy to integrate with your Angular application. First, you'll need a JSON API endpoint or file.

How we can add style to the particular component?

There are several ways to add styles to a component: By setting styles or styleUrls metadata. Inline in the template HTML. With CSS imports.


2 Answers

Update

Angular and SASS agreed on supporting ::ng-deep (instead of >>> or /deep/) a while ago until ::slotted or whatever makes it into browser standards becomes available in all browsers.

ViewEncapsulation.Emulated (default)

That's by design. Angular adds class names unique to components and rewrites the added styles to only apply to the components where they were added.

D3 generates HTML dynamically without Angulars knowledge and Angular can't apply the classes to make the styles apply on the generated HTML.

If you add the styles at the entry point HTML file, Angular also doesn't rewrite the styles and the added helper classes don't take effect.

ViewEncapsulation.None

With encapsulation: ViewEncapsulation.None Angular doesn't do this rewriting, therefore the result is similar to adding the HTML to the index.html.

"Shadow-piercing"

Alternatively you can use the recently introduced shadow piercing CSS combinators >>>, /deep/ and ::shadow (::shadow is just replaced by a and thus very limited). See also https://stackoverflow.com/a/36225709/217408 and the Plunker

:host /deep/ div {   color: red; } 

SASS

/deep/ works fine with SASS but the alias >>> doesn't.

The shadow-piersing CSS combinators are rewritten by Angular and they don't need to be supported by the browsers. Chrome supported them for a while but they are deprecated - but as said, that doesn't matter, because Angular rewrites them to use its encapsulation emulation.

ViewEncapsulation.Native

Angular doesn't support any way to style such components from the outside. Only if the browser provides support like CSS variables then these can be used.

like image 120
Günter Zöchbauer Avatar answered Sep 22 '22 13:09

Günter Zöchbauer


ViewEncapsulation will fix your problem.

import {Component,ViewEncapsulation} from 'angular2/core'  @Component({   selector: 'my-app',   encapsulation: ViewEncapsulation.None,   providers: [],    styles: [`      .bar {        fill: red;     }   `],   template: `     <div>       <svg class="chart"></svg>     </div>   `,   directives: [] }) 
like image 34
Nikhil Shah Avatar answered Sep 24 '22 13:09

Nikhil Shah