Подтвердить что ты не робот

Angular 2 Компонент - доступ к DOM (или создание компонента без шаблона, исключительно из JS)

Попытка играть с Angular 2 здесь... поняла, что она все еще в альфе.

Как мне получить доступ к элементам DOM из Component? В частности, я хотел бы использовать другие библиотеки, такие как d3 для создания пользовательского DOM из кода. Полагаю, мне нужно создать компонент и как-то подключить к жизненному циклу компонента, чтобы изменить DOM с d3... любую идею, с которой начать копать?

Я использую этот быстрый старт.

Спасибо!

4b9b3361

Ответ 1

Если вы не против использования Директивы вместо Компонента, это просто. Для Angular 2.0.0-alpha.33 в typescript вы можете использовать D3 для управления DOM путем инъекции ElementRef:

@Directive({
    selector:   'scatter-plot',
    lifecycle: [LifecycleEvent.onChange],
    properties: [ 'data' ]
})
export class ScatterPlot {

    root: Selection<any>;
    data: Array<ScatterPlotDataPoint>;

    x: (number) => number;
    y: (number) => number;

    defaultSize: string;
    circles: any;

    constructor(
        @Inject(ElementRef) elementRef: ElementRef,
        @Attribute('height') height: string,
        @Attribute('default-size') defaultSize: string
    ) {
        var el:HTMLElement = elementRef.nativeElement;
        this.root = d3.select(el);

        this.defaultSize = defaultSize ? defaultSize : "5";
        this.circles = this.root
            .append('svg')
            .attr('class', 'chart')
            .style({
                'width':  '100%',
                'height': height ? height + 'px': '',
            }).
            selectAll('circle');

    }

    render(newValue) {
        if (!newValue) return;

        this.x = d3.scale.linear().domain([-10, 110]).range([0, 250]);
        this.y = d3.scale.linear().domain([-10, 110]).range([100, 0]);

        this.circles = this.circles
            .data(newValue);

        this.circles.exit().remove();

        this.circles.enter()
            .append('circle');

        this.circles
            .transition()
            .attr("r", d => d.size ? d.size: this.defaultSize)
            .style("fill", d => d.color)
            .attr('cx', d => this.x(d.x))
            .attr('cy', d => this.y(d.y));

    }

    onChange() {
        this.render(this.data);
    }
}

Ответ 2

Использовать ElementRef

ElementRef будет вставлять текущий DOM node в ваш компонент. Служба ElementRef всегда будет локальной для вашего текущего DOM node.

Введя его, вы можете получить фактический DOM node с помощью nativeElement:

var el = elementRef.nativeElement

Как только вы это сделаете, вы можете манипулировать им так, как вам нравится, используя DOM-скриптинг или используя DOM-обертку, такую ​​как jQuery:

$(el)
  .append('<p>Some interesting Stuff')
  .addClass('my_class');

Но не делайте этого, если вы можете помочь ему

Помните, что, как и в случае с Angular 1, использование прямого манипулирования DOM не рекомендуется. Вы можете получить практически всю свою работу, используя шаблоны, и вы должны поддерживать этот способ работы большую часть времени.

Прямая манипуляция с DOM приводит к сложному, трудно понятному, труднопробному тестированию.

Бывают моменты, когда это может показаться лучшим решением. Например, если вам нужно интегрироваться с сторонней структурой с высокой степенью сложности, например с графической библиотекой.

Здесь приведенный пример (в ES6)

var AppComponent = ng.core
  .Component({
    selector: "app",
    template:
    `
      <div>Captured element</div>
    `
  })
  .Class({
    constructor: [ng.core.ElementRef, function(elementRef) {
      var el = elementRef.nativeElement
      el;
    }]
  })

Ответ 3

Примечание. [Устаревший]

Вы можете использовать "BrowserDomAdapter"
https://angular.io/docs/ts/latest/api/platform/browser/BrowserDomAdapter-class.html

import {BrowserDomAdapter} from 'angular2/platform/browser'

@Component({
  selector: 'dom',
  templateUrl: 'path/to/template.html',
  providers: [BrowserDomAdapter]
})
export class DomComponent {
  constructor(private _dom: BrowserDomAdapter) {
    var domIWant = this._dom.query('whatever you want to get');
  }
}

Процесс

  • import BrowserDomAdapter
  • применить поставщиков: [BrowserDomAdapter]
  • инициировать в конструкторе()
  • получить dom с помощью instanced BrowserDomAdapter

Ответ 5

Как упоминались другие плакаты: вы можете манипулировать DOM, введя ElementRef в директиву. Однако тщательно подумайте, действительно ли вам нужно это делать.

D3 - инструмент манипуляции DOM. Он позволяет привязывать объект данных к DOM node, а затем добавлять или удалять дочерние элементы из этого элемента в ответ на изменение значений данных. Это в значительной степени то, что делает Angular 2.

Конечно, D3 делает и другие вещи. Например, вы можете генерировать углы для круговой диаграммы или обычного распределения, и вы можете использовать D3 для этого.

Я знаю, что это не тот ответ, который вы ищете. Это не тот ответ, который я искал, но... Подумайте, нужно ли использовать D3 для манипуляций с DOM и привязки данных. Angular 2 уже имеет DOM-манипуляцию и привязку данных.