2015-10-28 26 views
72

ho integrato con successo angolare 2 (Alpha 44) con d3.js:Utilizzando d3.js con angolare 2

<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); 

tutto funziona bene. Ma la documentazione di Angular 2 per ElementRef afferma quanto segue:

Utilizzare questa API come ultima risorsa quando è necessario l'accesso diretto a DOM. Utilizzare invece i modelli e l'associazione dati forniti da Angular. In alternativa, date un'occhiata a {@link Renderer} che fornisce API che possono essere tranquillamente utilizzate anche quando l'accesso diretto agli elementi nativi non è supportato. Affidarsi all'accesso DOM diretto crea un legame stretto tra l'applicazione e i livelli di rendering, rendendo impossibile la separazione dei due e l'implementazione dell'applicazione in un web worker.

Ora sorge la domanda su come integrare D3.js con le API di Renderer?

+0

È questo in qualsiasi aiuto? http://www.ng-newsletter.com/posts/d3-on-angular.html – urosjarc

+0

Sto anche cercando di far funzionare D3 con angular 2. Nell'esempio sopra, posso vedere che fai riferimento allo script d3 in index.html, ma non riesco a vedere come ottieni la variabile d3 in app.js? – user2915962

+7

@ user2915962 - npm installa d3, assicura le esecuzioni di postinstall e d3.d.ts viene creato da tsd, quindi 'importa * come d3 da' d3/d3 '; ' – drewmoore

risposta

53

Per utilizzare Renderer, è necessario l'elemento HTML non elaborato (aka nativeElement). Quindi in pratica devi usare qualunque cosa sia la tua libreria, ottenere l'elemento raw e passarlo a Renderer.

Per esempio

// 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'avvertimento circa ElementRef è di usarlo direttamente. Ciò significa che questo è scoraggiato

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

Ma questo va bene

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

Per mostrare scopi è possibile utilizzarlo anche con jQuery

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

La mia raccomandazione è però attenersi a utilizzare ciò che angular2 ti consente di farlo facilmente senza dipendere da altre librerie.

Con pura angular2 ci sono due semplici modi

  • l'uso di direttive
// 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 {} 
  • Uso ViewChild con le variabili locali
@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'); 
    } 
} 

Ecco uno plnkr con tutti i casi che ho menzionato in questa risposta. Le tue esigenze potrebbero essere diverse, ovviamente, ma cerca di usare angular2 quando puoi.

+2

Quindi, per l'esempio di utilizzo di bootstrap plug-in collapse, avrei ragione nel dire che 'jQuery (this.el.nativeElement) .collapse ('show');' sarebbe un modo perfettamente accettabile per istanziare il plugin? – garethdn

+0

Immagino che l'approccio direttivo non funzionerebbe per gli h3 dinamici aggiunti in modo corretto? Esempio: http://plnkr.co/edit/U2lvYqtGvdf7kWoRg10N?p=preview – echonax

2

Ho riscontrato problemi con l'uso di ElementRef, non sono sicuro che l'API sia stata modificata. Così ho finito per usare ViewContainRef per ottenere l'elemento nativo.

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"); 
    }; 
} 
5

Prova questo:

npm install [email protected] --saveper impostare la versione è necessario

npm install @types/[email protected] --save o una versione più alto se si vuole d3 4+

e poi nella vostra ts do

import * as d3 from 'd3';

dovrebbe funzionare bene

+0

utilizzando l'ultimo d3 (v4) e basato sull'esempio di quickstart angolare 2 ho dovuto anche aggiungere ''d3': 'npm: d3'' per mappare e ''d3': {main: 'build/d3.js', defaultExtension: 'js'}' ai pacchetti nel file 'systemjs.config.js'. – Entrodus

+0

Ciao @Entrodus, ti dispiace darmi l'esatta sequenza di installazione, basata su Quickstart? Ho provato a seguire questo, incluso il mod del sistema che hai proposto, ma sono ancora bloccato (no ./build/d2.js, no ./build cartella). –

+0

@ StéphanedeLuca: 1.Impostare il quickstart angolare> 2.install d3 e typings per d3 versione 4.4.0> 3.added le direttive map e packages per d3 in system.config.js> 4.add import di d3 nel componente angolare che utilizza d3> 5.Victory. – Entrodus

2
npm install --save d3 

versione di controllo d3 in package.json e controllarla in node_modules troppo.

poi, nelle component.ts, importarlo come di seguito

import * as d3 from 'd3'; 
+0

Funziona anche in Angular 4? – fangio