I have a problem because I am trying to show some results about countries into a Pie Chart(HightCharts). I assign this information to a BehaviorSubject after it comes from an API call into the ApiService.
The first time, I receive the information in my chartComponent, it creates a Chart but the second one I need delete this chart and create a new one because users can modify results through a form that filters by continent and kind of metrics like population or AreaInSqkm.
This is the Api Call in the service:
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)
}
As you can see, I pass the data as the value of the BehaviorSubject and I receive information the changes in this value every time that someone modifies the form.
Later I create the chart in my chartComponent like this:
@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>
The main problem is that I am not able to check if exist a chart before and if it exists delete it a create a new one with the result caught through the subscription. I suppose that I should add something at the beginning of the createChart function with the Rederer2 Service but I don't know how.
Thanks!