Adding a host attribute to generated DOM elements

I am trying to integrate d3 and angular2 alpha.37 (started from here ). The problem I'm currently facing is that the created DOM elements do not get the attributes used in encapsulation with emulated style, so I cannot style them without setting the encapsulation of the view for the None (or Native, element, but I rather would rather emulate).

I managed to programmatically extract the required attribute from the element inside the component [1], and then add it to the generated elements [2], which works, but this is clearly incredibly hacky:

import {Component, View, Attribute, ElementRef, LifecycleEvent} from 'angular2/angular2'; import d3 from 'd3'; @Component({ selector: 'bar-graph', properties: [ 'data' ] }) @View({ template: '<div class="chart"></div>', styles: [`.chart { background: #eee; padding: 3px; } div.bar { width: 0; transition: all 1s ease-out; -moz-transition: all 1s ease-out; -webkit-transition: all 1s ease-out; } div.bar { font: 10px sans-serif; background-color: steelblue; text-align: right; padding: 3px; margin: 5px; color: white; box-shadow: 2px 2px 2px #666; }`] }) export class BarGraph implements LifecycleEvent.OnChanges { data: Array<number>; divs: any; constructor(elementRef: ElementRef, @Attribute('width') width: string, @Attribute('height') height: string) { var el:any = elementRef.nativeElement; var graph:any = d3.select(el); this.hostAttr = graph[0][0].children[0].attributes[1].name; //hack here [1] this.divs = graph. select('div.chart'). style({ 'width': width + 'px', 'height': height + 'px', }). selectAll('div.bar'); } render(newValue) { if (!newValue) return; this.divs.data(newValue) .enter().append('div') .classed('bar', true) .attr(this.hostAttr, true) //add the attribute here [2] .style('width', d => d + '%') .text(d => d + '%'); } onChanges() { this.render(this.data); } } 

Is there a recommended way to deal with such things (or should I stop redoing the DOM outside of Angular2)?

+6
source share
1 answer

Not a complete answer (for now), but perhaps useful information that can help in finding a solution:

  • The problem still exists in beta. Setting encapsulation of incrementation to None and using global styles is the only solution I could work with. Using Native did not seem to cause any elements to be added to the DOM at all, but I would have to do a few more tests to find out the reason.
  • The hack proposed by OP works and can be reorganized into a reasonable solution, at least in my opinion.
  • In the specific case of d3.js everything becomes even more complicated when introducing elements that are created inside the library; through methods in the d3.svg namespace. Undoubtedly, a workaround for this can also be found.
  • I believe the problem is bigger than d3 . There are many libraries that have their own DOM generation / manipulation mechanisms, and it is unrealistic to think that some of them will at some point be integrated into one or another angular2 application. In this sense, it is surprising that the problem does not seem to have appeared yet (or maybe my Google-fu is especially weak this week).

In terms of solutions, these are two approaches that I am now considering if no one comes up with something more pleasant:

  • Introducing a kind of postprocessor that processes the partial DOM tree and sets the attributes of the style area. Maybe as a directive?
  • Try decorating the renderer as shown here .
+1
source

All Articles