0

我有一个问题,因为我试图在饼图(HightCharts)中显示一些关于国家的结果。在它来自对 ApiService 的 API 调用之后,我将此信息分配给 BehaviorSubject。

第一次,我在我的 chartComponent 中收到信息,它创建了一个图表,但第二个我需要删除这个图表并创建一个新的,因为用户可以通过一个按大陆和指标类型(如人口或 AreaInSqkm)过滤的表单修改结果.

这是服务中的 Api 调用:

      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 的值传递,并且每次有人修改表单时我都会收到有关此值更改的信息。

稍后我在我的 chartComponent 中创建图表,如下所示:

@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>

主要问题是我无法检查之前是否存在图表,如果存在则删除它并创建一个新的图表,结果通过订阅捕获。我想我应该在 Rederer2 服务的 createChart 函数的开头添加一些东西,但我不知道如何。

谢谢!

4

1 回答 1

0

我会完全避免使用渲染器并使用angular2-highcharts库。

您可以将选项传递给chart库提供的元素。您还可以附加一个事件,该事件将在图表呈现后为您提供图表对象。这将允许您根据需要删除/添加系列。

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

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

在您订阅您的行为主题 observable 时,您可以检查图表是否存在。如果是,请更新现有图表。如果没有,请创建初始图表

// 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


旁注:您通常不应该在您的服务中订阅。相反,服务应该公开组件可以订阅的 observables。在这种情况下,解决方案可能看起来像这样plnkr

于 2017-12-28T17:31:28.680 回答