将host属性添加到生成的DOM元素

Ric*_*chL 6 javascript d3.js angular

我试图整合d3和angular2 alpha.37(从这里开始).我目前遇到的问题是生成的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);
  }

}
Run Code Online (Sandbox Code Playgroud)

是否有推荐的方法来处理这类事情(或者我应该停止修改Angular2之外的DOM)?

Rob*_*sen 1

还不是完整的答案,但也许一些有用的信息可以帮助找到解决方案:

  • 该问题在 beta.8 中仍然存在。将视图封装设置为None全局样式并使用全局样式是我可以使用的唯一解决方案。使用Native似乎根本没有任何元素被添加到 DOM 中,但我必须做更多的测试才能找出原因。
  • OP 提出的 hack 有效,并且可以重构为合理的解决方案,至少在我看来。
  • 在 的特定情况下d3.js,当引入由库内部创建的元素(例如通过命名空间中的方法)时,事情会变得更加棘手d3.svg。毫无疑问,也可以找到解决方法。
  • 我认为这个问题比d3然而更严重。有很多库都有自己的 DOM 生成/操作机制,并且认为其中一部分将在某个时候集成到某些或其他angular2应用程序中并非不现实。从这个意义上说,令人惊讶的是这个问题似乎还没有出现(或者也许我的 Google-fu 这周特别弱)。

就解决方案而言,我目前正在考虑以下两种方法,以防没有人想出更好的方法:

  1. 实现某种后处理器来遍历部分 DOM 树并设置样式范围属性。也许作为指令?
  2. 尝试装饰渲染器,如此处暗示的那样