web-dev-qa-db-fra.com

Angular 2 Component - Accédez au DOM (ou créez un composant sans modèle, uniquement à partir de JS)

Essayer de jouer avec Angular 2 ici ... a compris que c’est toujours en alpha.

Comment accéder aux éléments DOM depuis Component? Plus précisément, j'aimerais utiliser d'autres bibliothèques telles que d3 pour générer du DOM personnalisé à partir de code. Je suppose que j'ai besoin de créer un composant et de me brancher sur son cercle de vie pour modifier DOM avec d3 ... aucune idée par où commencer à creuser?

J'utilise ce quickstart repo .

Merci!

22
Anatoly

Si cela ne vous dérange pas d’utiliser Directive au lieu de Component, c’est simple. Pour Angular 2.0.0-alpha.33 dans TypeScript, vous pouvez utiliser D3 pour manipuler le DOM en injectant un 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);
    }
}
19
Hardbyte

Utiliser ElementRef

ElementRef va injecter le nœud DOM actuel dans votre composant. Le service ElementRef sera toujours local sur votre nœud DOM actuel.

Après l'avoir injecté, vous pouvez obtenir le nœud DOM actuel à l'aide de nativeElement:

var el = elementRef.nativeElement

Une fois que vous avez cela, vous pouvez le manipuler comme bon vous semble, en utilisant un script DOM ou en utilisant un wrapper DOM comme jQuery:

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

Mais ne faites pas cela si vous pouvez l'aider

Sachez que, comme avec Angular 1, l’utilisation de la manipulation directe du DOM est déconseillée. Vous pouvez effectuer à peu près tout votre travail à l'aide de modèles, et vous devriez privilégier cette méthode de travail la plupart du temps.

La manipulation directe du DOM conduit à du code compliqué, difficile à comprendre, difficile à tester.

Il y a cependant des moments où cela peut sembler être la meilleure solution. Par exemple, si vous devez intégrer une structure tierce, très complexe, telle qu'une bibliothèque graphique.

Voici un exemple travaillé (dans 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;
    }]
  })
7
superluminary

Note: [Obsolète]

Vous pouvez utiliser "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');
  }
}

Processus

  1. importer BrowserDomAdapter
  2. appliquer des fournisseurs: [BrowserDomAdapter]
  3. initier dans constructeur ()
  4. get dom en utilisant instanced BrowserDomAdapter
5
taz

Comme d'autres affiches l'ont mentionné: vous pouvez manipuler le DOM en injectant ElementRef dans la directive. Cependant, réfléchissez bien si vous avez réellement besoin de le faire. 

D3 est un outil de manipulation DOM. Il vous permet de lier un objet de données à un nœud DOM, puis d'ajouter ou de supprimer des éléments enfants de cet élément en réponse à la modification des valeurs de données. C'est à peu près exactement ce que fait Angular 2.

Bien sûr, D3 fait aussi d'autres choses. Vous pouvez générer des angles pour un diagramme à secteurs, ou une distribution normale, par exemple, et vous pouvez utiliser D3 pour cela.

Je sais que ce n'est pas la réponse que vous recherchez. Ce n'est pas la réponse que je cherchais, mais ... Déterminez si vous devez utiliser D3 pour la manipulation du DOM et la liaison de données. Angular 2 a déjà une manipulation DOM et une liaison de données.

0
superluminary

Ce document ( http://victorsavkin.com/post/118372404541/the-core-concepts-of-angular-2 ) mentionne des "directives de style décorateur" qui, je crois, sont décrites avec un peu plus de détails et de base. exemple ici ( https://angular.io/api/core/Directive ).

0