我试图整合d3和angular2 alpha.37(从here开始) . 我目前遇到的问题是生成的DOM元素没有设置它们的样式,而没有将元素的视图封装设置为None(或Native,但我宁愿使用模拟) .
我设法以编程方式从组件[1]中的元素中提取所需的属性,然后将其添加到生成的元素[2],这确实有效,但这显然非常难以理解:
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);
}
}
是否有推荐的方法来处理这类事情(或者我应该停止修改Angular2之外的DOM)?
1 回答
还不是一个完整的答案,但也许一些有用的信息可以帮助找到解决方案:
这个问题在beta.8中仍然存在 . 将视图封装设置为
None
并使用全局样式是我可以开始工作的唯一解决方案 . 使用Native
似乎导致根本没有元素被添加到DOM中,但是我必须做更多的测试来找出原因 .OP提出的黑客工作,至少在我看来,可以重构为合理的解决方案 .
在
d3.js
的特定情况下,当引入由库内部创建的元素时,事情变得更加棘手,例如通过d3.svg
命名空间中的方法 . 毫无疑问,也可以找到解决方法 .我认为问题大于
d3
. 有很多库都有自己的DOM生成/操作机制,并且认为其中的一部分将在某些时候集成到某些或其他应用程序中并不是不现实的 . 从这个意义上来说,令人惊讶的是这个问题似乎还未出现(或者本周我的Google-fu特别弱) .在解决方案方面,这些是我目前正在考虑的两种方法,以防没有人提出更好的东西:
实现某种后处理器,它可以遍历部分DOM树并设置样式范围属性 . 也许作为指令?
尝试装饰渲染器,如暗示here .