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

6
我正在尝试集成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);
  }

}

有没有推荐的方法来处理这种情况(或者我应该停止在Angular2之外的DOM上调整)?


1
如果你想得到答案,至少你需要升级到beta.0版本。 - Eric Martinez
@EricMartinez 在beta.7上也遇到了同样的问题。 - Robby Cornelissen
1个回答

1

虽然还不是完整的答案,但以下信息可能有助于找到解决方案:

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

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接