NgxCharts for Angular 14 -

260 views Asked by At

i have to code a project with angular 14 and the ngx charts library, but it seems that the line chart is not working, my console.log display the data (name, value) in console but the line chart dont appear, there is my code :

// line chart component

import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Country } from '../core/models/Olympic';
import { Participation } from '../core/models/Participation';
import { OlympicService } from '../core/services/olympic.service';

@Component({
  selector: 'app-line-chart',
  templateUrl: './line-chart.component.html',
  styleUrls: ['./line-chart.component.scss'],
})
export class LineChartComponent implements OnInit, OnChanges {
  @Input() data!: Country[];
  @Input() selectedCountry!: Country;
  view: [number, number] = [700, 300];
  single: any[] = [];
  totalMedalsCount!: number;
  totalAthleteCount!: number;

  // Chart properties
  showXAxis = true;
  showYAxis = true;
  gradient = false;
  showLegend = true;
  showXAxisLabel = true;
  showYAxisLabel = true;
  xAxisLabel = 'Years';
  yAxisLabel = 'Medals Count';



  constructor(private OlympicService: OlympicService) {}

  ngOnInit(): void {
    this.OlympicService.loadInitialData().subscribe(() => {
      this.getData();
    });
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['data'] && changes['selectedCountry']) {
      this.processData();
    }
  }

  getData(): void {
    this.OlympicService.getOlympics().subscribe((data: Country[]) => {
      this.data = data;
      // Sélectionnez un pays par défaut
      this.selectedCountry = this.data[0];
      this.processData();
      console.log(this.single)
    });
  }

  processData(): void {
    if (this.selectedCountry) {
      console.log(this.selectedCountry.participations)
      this.single = this.selectedCountry.participations.map((participation: Participation) => {
        return {
          name: participation.year.toString(),
          value: participation.medalsCount,
        };
      });


      // Calculer le total des médailles et le total des athlètes
    this.totalMedalsCount = this.selectedCountry.participations.reduce((total, participation) => {
      return total + participation.medalsCount;
    }, 0);

    this.totalAthleteCount = this.selectedCountry.participations.reduce((total, participation) => {
      return total + participation.athleteCount;
    }, 0);
    }
  }

}
<!-- This is the template of the line chart component. -->

<div class="container">
  <div class="title">
    <h2>{{ selectedCountry.country }}</h2>
  </div>
  <div class="description">
    <p class="legend">Number of entries: {{ selectedCountry.participations.length }}</p>
    <p class="legend">Total number of medals {{ totalMedalsCount }} </p>
    <p class="legend">Total number of athletes {{ totalAthleteCount }}</p>
  </div>
  <ngx-charts-line-chart
  [view]="view"
  [results]="single"
  [xAxis]="showXAxis"
  [yAxis]="showYAxis"
  [showXAxisLabel]="showXAxisLabel"
  [showYAxisLabel]="showYAxisLabel"
  [xAxisLabel]="xAxisLabel"
  [yAxisLabel]="yAxisLabel"
></ngx-charts-line-chart>
</div>

import { Component, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
import { OlympicService } from 'src/app/core/services/olympic.service';
import { Country } from '../core/models/Olympic';
import { map, switchMap } from 'rxjs/operators';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';

@Component({
  selector: 'app-pays-detail',
  templateUrl: './pays-detail.component.html',
  styleUrls: ['./pays-detail.component.scss'],
})
export class PaysDetailComponent implements OnInit {
  public olympics$!: Observable<any>;
  public countryDataArray: Country[] = [];
  public data: Country[] = [];
  public selectedCountry: Country | undefined;

  constructor(private OlympicService: OlympicService, private router: Router, private route: ActivatedRoute) {}

  ngOnInit(): void {
    this.OlympicService.loadInitialData().subscribe(() => {
      this.olympics$ = this.OlympicService.getOlympics(); // Initialisation de olympics$ avec le flux de données

      this.olympics$.subscribe((data: Country[]) => {
        this.data = data; // Affectez les données récupérées à la propriété data
      });

      this.route.paramMap.pipe(
        switchMap((params: ParamMap) => {
          const countryId = params.get('id');
          if (countryId) {
            return this.olympics$.pipe(
              map((data: any) => data.find((country: Country) => country.id.toString() === countryId) as Country)
            );
          } else {
            return of(null);
          }
        })
      ).subscribe((selectedCountry: Country | null) => {
        if (selectedCountry !== null) {
          this.selectedCountry = selectedCountry;
        }
      });
    });
  }

  goback() {
    window.history.back();
  }

  isCountrySelected(): boolean {
    return this.selectedCountry !== undefined;
  }

}

<!-- Description: Pays detail component template -->

<div class="container d-flex flex-row">
  <div>
    <ng-container *ngIf="selectedCountry">
      <app-line-chart [data]="data" [selectedCountry]="selectedCountry"></app-line-chart>
    </ng-container>


  </div>

  <div>
    <button class="btn" (click)="goback()">Back</button>
  </div>
</div>

// app module

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './pages/home/home.component';
import { NotFoundComponent } from './pages/not-found/not-found.component';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { PieChartComponent } from './pie-chart/pie-chart.component';
import { LineChartComponent } from './line-chart/line-chart.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PaysDetailComponent } from './pays-detail/pays-detail.component';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    NotFoundComponent,
    PieChartComponent,
    LineChartComponent,
    PaysDetailComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    NgxChartsModule,
    BrowserAnimationsModule
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './pages/home/home.component';
import { NotFoundComponent } from './pages/not-found/not-found.component';
import { PaysDetailComponent } from './pays-detail/pays-detail.component';

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
  },
  {
    path: 'detail/:id',
    component: PaysDetailComponent,
  },
  {
    path: '**',
    component: NotFoundComponent,
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { map } from 'rxjs/operators';


@Injectable({
  providedIn: 'root',
})
export class OlympicService {
  private olympicUrl = './assets/mock/olympic.json';
  private olympics$ = new BehaviorSubject<any>(undefined);

  constructor(private http: HttpClient) {}

  loadInitialData() {
    return this.http.get<any>(this.olympicUrl).pipe(
      tap((value) => this.olympics$.next(value)),
      catchError((error, caught) => {
        // TODO: improve error handling
        console.error(error);
        // can be useful to end loading state and let the user know something went wrong
        this.olympics$.next(null);
        return caught;

      })
    );
  }

  getCountryData(countryName: string) {
    return this.getOlympics().pipe(
      map((olympics: any[]) => {
        return olympics.find((country: any) => country.country === countryName);
      })
    );
  }


  getOlympics() {
    return this.olympics$.asObservable();
  }
}

// Model for Country

import { Participation } from './Participation';

export interface Country {
  id: number;
  name: string;
  country: string;
  participations: Participation[];
}

// Model for Participation

export interface Participation {
  id: number;
  year: number;
  city: string;
  medalsCount: number;
  athleteCount: number;
}

this is what i have on my local server

I just wan't the pays details page to display the data of the line chart component for the country selected

0

There are 0 answers