0

파이 차트 (HightCharts)에 국가 별 결과를 표시하려고하기 때문에 문제가 있습니다. ApiService로 API를 호출 한 후에이 정보를 BehaviorSubject에 할당합니다.차트를 제거하고 내 behaviorSubject가 값을 변경 할 때마다 새 차트를 작성하는 방법

처음으로 ChartComponent에 정보를 수신했지만 차트를 만들지 만 두 번째는이 차트를 삭제하고 사용자가 대륙 별 및 메트릭 종류별로 필터링하는 양식을 통해 결과를 수정할 수 있으므로 새 차트를 만들어야합니다. 인구 또는 AreaInSqkm와 유사합니다. 당신이 볼 수 있듯이

 public dataObservable = this.data.asObservable(); 
 
     private data = new BehaviorSubject<any>(null); 
 

 
    
 
    direction: String = "dsc"; 
 
    
 

 
    public filters: any = { 
 
     continent : "All", 
 
     metric: "None", 
 
     quantity: 5, 
 
    }; 
 

 

 
    url = "some URL"; 
 

 
    constructor(private http : Http) { } 
 
     getCountries(){ 
 
      return this.http.get(this.url) 
 
      .map(res=>res.json()) 
 
      .map((data)=>data.geonames.filter((country)=>{ 
 
       if(this.filters.continent !== "All"){ 
 
       return country.continent == this.filters.continent 
 
       }else{ 
 
       return country.continent 
 
       } 
 
      }) 
 
     ) 
 
      .map((data)=>{   
 
       if(this.filters.metric == "population"){ 
 
       return this.sortByPopulation(data, this.direction).slice(0, this.filters.quantity) 
 
       }else if(this.filters.metric == "areaInSqKm"){ 
 
       return this.sortByArea(data, this.direction).slice(0, this.filters.quantity)   
 
       } 
 
       return data.slice(0, this.filters.quantity); 
 
      }) 
 
      .subscribe((data)=>{ 
 
       this.setData(data); 
 
      }) 
 
      
 
     } 
 

 

 
    sortByPopulation(data, direction){ 
 
    if(direction =="asc"){ 
 
     data.sort((a, b)=>{ 
 
     return a["population"] - b["population"] 
 
     }) 
 
    } else{ 
 
     data.sort((a, b)=>{ 
 
     return b["population"] - a["population"] 
 
     }) 
 
    } 
 
    return data 
 
    } 
 

 
    sortByArea(data, direction){ 
 
    if(direction =="asc"){ 
 
     data.sort((a, b)=>{ 
 
     return a["areaInSqKm"] - b["areaInSqKm"] 
 
     }) 
 
    } else{ 
 
     data.sort((a, b)=>{ 
 
     return b["areaInSqKm"] - a["areaInSqKm"] 
 
     }) 
 
    } 
 
    return data 
 
    } 
 

 
    updateFilters(filters){ 
 
    this.filters = filters 
 
    } 
 

 

 
    setData(data){ 
 
    this.data.next(data) 
 
    } 
 

, 내가 BehaviorSubject의 값으로 데이터를 전달하며이 값의 변화 정보를 수신 :

서비스의 API 호출입니다 누군가가 양식을 수정할 때마다.

@Component({ 
 
    selector: 'chart', 
 
    templateUrl: './chart.component.html', 
 
    styleUrls: ['./chart.component.scss'] 
 
}) 
 
export class ChartComponent implements OnInit, AfterViewInit { 
 
    
 
    element : any; 
 
    opts: Object = {}; 
 
    container : any; 
 

 
    @Input() 
 
    values: Array<Object>; 
 

 
    getCountriesSubscription: Subscription = null; 
 

 
    
 
    
 
    chartValues: any = [] 
 

 
    @ViewChild('chart') chart: ElementRef 
 
    constructor(
 
     private renderer : Renderer2, 
 
     private api : ApiService, 
 
     private cdRef : ChangeDetectorRef 
 
     
 
    ) { } 
 

 
    ngOnInit() { 
 

 
    
 

 
    } 
 

 
    ngAfterViewInit(){ 
 

 
    this.getCountriesSubscription = this.api.dataObservable 
 
    .subscribe((data)=>{ 
 
     if(data){ 
 
      data.map((element)=>{ 
 
       this.generateChartValues(element, this.api.filters.metric) 
 
      }) 
 

 
      this.generateChartOptions(this.chartValues); 
 
      this.createChart() 
 
      
 
      this.cdRef.markForCheck(); 
 
      console.log(this.chartValues[0]) 
 
     } 
 

 
    }) 
 
    
 
    } 
 

 
    createChart(){ 
 

 
    this.container = this.renderer.createElement("div"); 
 
    this.renderer.addClass(this.container, "mychart"); 
 
    let chart = new Highcharts.Chart(this.container,this.opts) 
 
    this.renderer.appendChild(this.chart.nativeElement, this.container) 
 
    console.log(this.container) 
 
     
 
    this.cdRef.markForCheck(); 
 
    
 
    } 
 
    
 

 

 
    generateChartOptions(chartValues){ 
 
    this.opts = { 
 
     chart: { 
 
      plotBackgroundColor: null, 
 
      plotBorderWidth: null, 
 
      plotShadow: false, 
 
      type: 'pie' 
 
     }, 
 
     title: { 
 
      text: `Countries in by ${this.api.filters.metric}` 
 
     }, 
 
     series: [{ 
 
     name: 'Total', 
 
     colorByPoint: true, 
 
     data: chartValues 
 
     }] 
 
    }; 
 
    } 
 

 
    generateChartValues(data, metric){ 
 
    if(metric == "population"){ 
 
     this.chartValues.push({ name: data.countryName, y: parseInt(data.population) }); 
 
    } 
 
    if(metric == "areaInSqKm"){ 
 
     this.chartValues.push({ name: data.countryName, y: parseInt(data.areaInSqKm) }); 
 
    } 
 
    if(metric == "None"){  
 
     this.chartValues.push({ name: data.countryName, y: 1}); 
 
    } 
 
    } 
 

 

 
}
<div #chart class="chartplace"> 
 
    
 
</div>

가장 큰 문제는 내가 전에 차트를 존재 여부를 확인 할 수없는 오전과 존재하는 경우 삭제 :

나중에 나는이처럼 내 chartComponent의 차트를 만들 a 구독을 통해 발견 된 결과로 새로운 것을 생성하십시오. 내가 Rederer2 서비스와 createChart 함수의 시작 부분에 뭔가를 추가해야 겠지만 어떻게 해야할지 모르겠다.

감사합니다.

+0

일정으로이 차트가 업데이트되기를 기대합니까? 행동 과제가 정말로 필요한가요? 아니면 데이터가 한 번만로드되도록 차트가 필요합니까? – LLai

답변

0

렌더러를 완전히 피하고 angular2-highcharts 라이브러리를 사용합니다.

라이브러리에서 제공하는 chart 요소로 옵션을 전달할 수 있습니다. 차트 렌더링 후 차트 개체를 제공하는 이벤트를 첨부 할 수도 있습니다. 이렇게하면 필요에 따라 시리즈를 제거/추가 할 수 있습니다.

// component.html 
<chart [options]="options" (load)="saveInstance($event.context)"></chart> 

// component.ts 
saveInstance(chartInstance) { 
    this.chart = chartInstance; 
} 

귀하의 행동 제목을 관찰 할 수있는 경우 차트가 있는지 확인할 수 있습니다. 그렇다면 기존 차트를 업데이트하십시오. 이 초기 차트 여기

// component.ts 
.subscribe(data => { 
    // if chart exists, update chart 
    if(this.chart){ 
     // remove existing series, and add new series 
     this.chart.series[0].remove(false); 
     this.chart.addSeries({ 
      data: data 
     }, true); 
    }else{ 
     // else generate chart initially 
     this.options = this.generateOptions(data); 
    } 
}); 

를 작성하지 않는 경우이 기능을


(!) 참고를 시연 plnkr입니다 : 당신은 일반적으로 서비스 내에서 가입해서는 안된다. 대신 서비스는 구성 요소가 구독 할 수있는 관찰 가능 항목을 노출해야합니다. 이 경우 솔루션은 다음과 같이 보일 수 있습니다. plnkr