web-dev-qa-db-fra.com

Utilisation de D3.js avec Angular 2

J'ai intégré avec succès Angular 2 (Alpha 44) à D3.js:

<html>
<head>
<title>Angular 2 QuickStart</title>
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script>
  System.config({packages: {'app': {defaultExtension: 'js'}}});
  System.import('app/app');
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

app.js:

/// <reference path="./../../typings/tsd.d.ts" />

import {Component, bootstrap, ElementRef} from 'angular2/angular2';

@Component({
  selector: 'my-app',
  template: '<h1>D3.js Integrated if background is yellow</h1>',
  providers: [ElementRef]
})
class AppComponent { 
  elementRef: ElementRef;

  constructor(elementRef: ElementRef) {
   this.elementRef = elementRef;
  }

afterViewInit(){
    console.log("afterViewInit() called");
    d3.select(this.elementRef.nativeElement).select("h1").style("background-color", "yellow");
  }
}
bootstrap(AppComponent);

Tout fonctionne bien. Mais la documentation de Angular 2 pour ElementRef indique ce qui suit:

Utilisez cette API en dernier recours lorsqu'un accès direct à DOM est requis. Utilisez plutôt des modèles et des liaisons de données fournis par Angular. Sinon, jetez un coup d'œil à {@link Renderer}, qui fournit une API qui peut être utilisée en toute sécurité même lorsque l'accès direct aux éléments natifs n'est pas pris en charge. Le recours à un accès DOM direct crée un couplage étroit entre votre application et les couches de rendu, ce qui rend impossible la séparation des deux et le déploiement de votre application dans un programme de travail Web.

Maintenant, la question se pose de savoir comment intégrer D3.js aux API de Renderer?

75
Zia Khan

Pour utiliser Renderer, vous avez besoin de l’élément HTML brut (aussi appelé nativeElement). Donc, fondamentalement, vous devez utiliser votre bibliothèque, obtenir l’élément brut et le transmettre à Renderer.

Par exemple

// h3[0][0] contains the raw element
var h3 = d3.select(this.el.nativeElement).select('h3');
this.renderer.setElementStyle(h3[0][0], 'background-color', 'blue');

L'avertissement concernant ElementRef concerne son utilisation directe. Cela signifie que cela est découragé

elementRef.nativeElement.style.backgroundColor = 'blue';

Mais c'est bien

renderer.setElementStyle(elementRef.nativeElement, 'background-color', 'blue');

Pour montrer, vous pouvez aussi l’utiliser avec jQuery

// h2[0] contains the raw element
var h2 = jQuery(this.el.nativeElement).find('h2');
this.renderer.setElementStyle(h2[0], 'background-color', 'blue');

Ma recommandation est cependant d’utiliser ce que angular2 vous fournit pour le faire facilement sans dépendre d’une autre bibliothèque.

Avec pure angular2, vous avez deux solutions simples

  • Utilisation de directives
// This directive would style all the H3 elements inside MyComp
@Directive({
    selector : 'h3',
    Host : {
        '[style.background-color]' : "'blue'"
    }
})
class H3 {}

@Component({
    selector : 'my-comp',
    template : '<h3>some text</h3>',
    directives : [H3]
})
class MyComp {}
  • Utilisation de ViewChild avec des variables locales
@Component({
    selector : 'my-comp',
    template : '<h3 #myH3>some text</h3>',
})
class MyComp {
    @ViewChild('myH3') myH3;
    ngAfterViewInit() {
        this.renderer.setElementStyle(this.myH3.nativeElement, 'background-color', 'blue');
    }
}

Voici un plnkr avec tous les cas que j'ai mentionnés dans cette réponse. Bien sûr, vos exigences peuvent différer, mais essayez d’utiliser angular2 chaque fois que vous le pouvez.

54
Eric Martinez

Essaye ça:

npm install [email protected] --savepour définir la version dont vous avez besoin

npm install @types/[email protected] --saveou une version supérieure si vous voulez d3 4 +

puis dans votre ts do

import * as d3 from 'd3';

Devrait bien fonctionner

5
Pian0_M4n

J'avais du mal à utiliser ElementRef, je ne sais pas si cette API a changé. J'ai donc fini par utiliser ViewContainRef pour obtenir le nativeElement.

import {Component, ViewContainerRef, OnInit} from '@angular/core';
declare var d3:any;
@Component({
    selector: 'line-chart',
    directives: [],
    template: `<div class="sh-chart">chart</div>`
})
export class LineChart implements OnInit{
    elem ;
    constructor(private viewContainerRef:ViewContainerRef) {}
    ngOnInit(){
        this.elem = this.viewContainerRef.element.nativeElement;

        d3.select(this.elem).select("div").style("background-color", "yellow");
    };
}
3
Hello Dave
npm install --save d3

vérifiez la version de d3 dans package.json et vérifiez-la également dans node_modules.

puis, dans le composant.ts, importez-le comme suit

import * as d3 from 'd3';
3
user7803780