0
votes

My HTML markup look as follows where i am using piechart of NG2-Chart library which has dependency on chart.js:

<h2>Home</h2>
<div style="display: block">
    <canvas baseChart class="chart"
            [data]="pieChartData"
            [labels]="pieChartLabels"
            [chartType]="pie"
            (chartHover)="chartHovered($event)"
            (chartClick)="chartClicked($event)">
    </canvas>
</div>

I have written following code add it works perfectly fine. I can see the graph and get calls to eventhandlers too. My component code (working) looks as follows:

import {Component, OnInit, AfterViewInit, AfterContentInit} from '@angular/core';
import {NgClass} from '@angular/common';

import {PieChartData} from '../shared/pie-chart-data';
import {HotelsService} from '../components/hotel/hotels.service';
import {Hotel} from '../entities/hotel';


import * as _ from 'underscore/underscore';

@Component({
    selector:'home'
    , templateUrl:'app/home/home.component.html'
})
export class HomeComponent implements OnInit{
    hotels: Hotel[];
    hotelCountByCity; 
    data = new PieChartData();

    pieChartData = [];
    pieChartLabels=[];

    constructor(private _hotelsService: HotelsService){}

    ngOnInit(){
        this.getActiveHotelsByCity();        

        console.log("On Init");
    }

    // events
    public chartClicked(e:any):void {
        // TODO : should open another chart which is not decided.
    }

    public chartHovered(e:any):void {
        // TODO : do something
    }

    private getActiveHotelsByCity(){ 
        //this.data.pieChartType = "pie";
        this.pieChartLabels = ["One", "Two", "Three"]; 
        this.pieChartData = [100,200,300];
    }
}

But When i try to get the data from web service and assign it to piechart, I get weird errors. My component code (not working) :

import {Component, OnInit, AfterViewInit, AfterContentInit} from '@angular/core';
import {NgClass} from '@angular/common';

import {PieChartData} from '../shared/pie-chart-data';
import {HotelsService} from '../components/hotel/hotels.service';
import {Hotel} from '../entities/hotel';

import * as _ from 'underscore/underscore';

@Component({
    selector:'home'
    , templateUrl:'app/home/home.component.html'
})
export class HomeComponent implements OnInit{
    hotels: Hotel[];
    hotelCountByCity; 
    data = new PieChartData();

pieChartData = [];
pieChartLabels=[];

constructor(private _hotelsService: HotelsService){}

ngOnInit(){
    this.getActiveHotelsByCity();        

    console.log("On Init");
}

// events
public chartClicked(e:any):void {
    // TODO : should open another chart which is not decided.
}



   public chartHovered(e:any):void {
        // TODO : do something
    }

    private getActiveHotelsByCity(){  
        this._hotelsService.getAllActiveHotels()
                                .subscribe(
                                    res => this.hotelCountByCity =
                                                    _.countBy(
                                                        res.data.hotels
                                                        ,function(hotel: Hotel) {
                                                            return hotel.address.city;
                                                        })
                                    ,null
                                    , ()=> {
                                        this.pieChartLabels = _.keys(this.hotelCountByCity);
                                        this.pieChartData = _.values(this.hotelCountByCity);
                                        console.log("Reached success part of request");
                                    }
                                );
    }
}

The stack tress for error I get at first is as follows:

EXCEPTION: Uncaught (in promise): TypeError: Cannot set property stack of [object Object] which has only a getter TypeError: Cannot set property stack of [object Object] which has only a getter at assignAll (http://localhost:3000/node_modules/zone.js/dist/zone.js:704:29) at ViewWrappedError.ZoneAwareError (http://localhost:3000/node_modules/zone.js/dist/zone.js:775:16) at ViewWrappedError.BaseError [as constructor] (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:1104:38) at ViewWrappedError.WrappedError [as constructor] (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:1133:20) at new ViewWrappedError (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:5106:20) at _View_HomeComponent_Host0.DebugAppView._rethrowWithContext (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:9427:27) at _View_HomeComponent_Host0.DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:9413:22) at ViewRef_.detectChanges (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:7398:24) at RouterOutlet.activate (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:3458:46) at ActivateRoutes.placeComponentIntoOutlet (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:2955:20) at ActivateRoutes.activateRoutes (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:2933:26) at eval (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:2902:23) at Array.forEach (native) at ActivateRoutes.activateChildRoutes (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:2901:33) at ActivateRoutes.activate (http://localhost:3000/node_modules/@angular/router/bundles/router.umd.js:2896:18)

I realise this is not real error after digging around on internet. I found some advise on internet to locate the real error and the real error i found was:

"TypeError: Chart.controllers[meta.type] is not a constructor at Chart.Controller. (http://localhost:3000/node_modules/chart.js/dist/Chart.bundle.js:8508:24) at Object.helpers.each (http://localhost:3000/node_modules/chart.js/dist/Chart.bundle.js:9345:15) at Chart.Controller.buildOrUpdateControllers (http://localhost:3000/node_modules/chart.js/dist/Chart.bundle.js:8497:12) at Chart.Controller.initialize (http://localhost:3000/node_modules/chart.js/dist/Chart.bundle.js:8356:7) at new Chart.Controller (http://localhost:3000/node_modules/chart.js/dist/Chart.bundle.js:8339:6) at new Chart (http://localhost:3000/node_modules/chart.js/dist/Chart.bundle.js:10684:21) at BaseChartDirective.getChartBuilder (http://localhost:3000/node_modules/ng2-charts/components/charts/charts.js:73:16) at BaseChartDirective.refresh (http://localhost:3000/node_modules/ng2-charts/components/charts/charts.js:114:27) at BaseChartDirective.ngOnInit (http://localhost:3000/node_modules/ng2-charts/components/charts/charts.js:18:18) at Wrapper_BaseChartDirective.detectChangesInInputProps (/ChartsModule/BaseChartDirective/wrapper.ngfactory.js:89:53) at _View_HomeComponent0.detectChangesInternal (/AppModule/HomeComponent/component.ngfactory.js:74:32) at _View_HomeComponent0.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:9305:18) at _View_HomeComponent0.DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:9410:48) at _View_HomeComponent_Host0.AppView.detectViewChildrenChanges (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:9331:23) at _View_HomeComponent_Host0.detectChangesInternal (/AppModule/HomeComponent/host.ngfactory.js:33:8)"

I am not sure where to go from here. I have posted issue on ng2-charts gihub repo. I am stuck and i will really appreciate your help.

1
hello can you show me console output of this.pieChartLabels = _.keys(this.hotelCountByCity); this.pieChartData = _.values(this.hotelCountByCity); you are doing mistake here. its not in format which is required by ng2chart. if possible add plnkr alsoAmit kumar
ng2-chart lables is of type string[] and data of number []. I have used this same code before upgrading ng2-chart library and angular 2 final version. This problem occured when I updated the app.Darshan Puranik
well i am using ng2-chart with angular 2.4.1 and ng2-charts:1.4.4. your pie label and data should be in this form pieChartLabels:string[] = ['string1', 'string2', 'string3']; but i if you use _.key it will product something like 0:'string1' but we want only string1 its index is not required. can you use foreach and push all these string data values using array push in a variable and then assign to pieChartLabels.Amit kumar
and at the keep default values pieChartLabels:string[] = ['loading']; public pieChartData:number[] = [100]; can you try it once.Amit kumar

1 Answers

0
votes

I did some research on internet and read the documentation. I couldn't find the definite answer for my problem. Following process worked for me:

  1. I downgraded chart.js from 2.4.0 to 2.3.0
  2. I added the boolean to my component to indicate data was received from RESTApi or not. I used that flag to display canvas using *ngIf.

HTML markup looks as follows:

<canvas 
            baseChart 
            class="chart"
            [data]="data.pieChartData"
            [labels]="data.pieChartLabels"
            [chartType]="data.pieChartType"
            (chartHover)="chartHovered($event)"
            (chartClick)="chartClicked($event)"
            *ngIf="isDataAvailable"
            >
    </canvas>