[angular] Angular 2와 함께 D3.js 사용

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

모든 것이 잘 작동합니다. 그러나 ElementRef에 대한 Angular 2 문서에는 다음이 나와 있습니다.

DOM에 직접 액세스해야하는 경우이 API를 최후의 수단으로 사용하십시오. 대신 Angular에서 제공하는 템플릿 및 데이터 바인딩을 사용하십시오. 또는 네이티브 요소에 대한 직접 액세스가 지원되지 않는 경우에도 안전하게 사용할 수있는 API를 제공하는 {@link Renderer}를 살펴보세요. 직접 DOM 액세스에 의존하면 애플리케이션과 렌더링 레이어간에 긴밀한 결합이 생성되어 두 레이어를 분리하고 애플리케이션을 웹 작업자에 배포하는 것이 불가능합니다.

이제 D3.js를 Renderer API와 통합하는 방법에 대한 질문이 생깁니다.



답변

Renderer를 사용하려면 원시 HTML 요소 (일명 nativeElement)가 필요합니다. 따라서 기본적으로 라이브러리가 무엇이든 사용하고 원시 요소를 가져 와서 Renderer에 전달해야합니다.

예를 들면

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

ElementRef에 대한 경고는 직접 사용하는 것입니다. 이것은 이것이 낙담 함을 의미합니다

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

하지만 괜찮아

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

목적을 보여주기 위해 jQuery와 함께 사용할 수 있습니다.

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

내 권장 사항은 angular2가 제공하는 것을 사용하여 다른 라이브러리에 의존하지 않고 쉽게 수행하는 것입니다.

순수한 각도 2를 사용하면 두 가지 쉬운 방법이 있습니다.

  • 지시문 사용
// 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 {}
  • 지역 변수와 함께 ViewChild 사용
@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');
    }
}

이 답변에서 언급 한 모든 사례 가 담긴 plnkr 이 있습니다. 물론 요구 사항은 다를 수 있지만 가능할 때마다 angular2를 사용하십시오.


답변

이 시도:

npm install d3@3.5.36 --save 필요한 버전을 설정하려면

npm install @types/d3@3.5.36 --save
또는 d3 4+를 원한다면 더 높은 버전

그리고 당신의 ts

import * as d3 from 'd3';

잘 작동해야합니다.


답변

npm install --save d3

package.json에서 d3 버전을 확인하고 node_modules에서도 확인하십시오.

그런 다음 component.ts에서 다음과 같이 가져옵니다.

import * as d3 from 'd3';


답변

ElementRef를 사용하는 데 문제가 있었는데 해당 API가 변경되었는지 확실하지 않습니다. 그래서 NativeElement를 얻기 위해 ViewContainRef를 사용했습니다.

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


답변