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