how to pass json data into an array in angular

2.2k views Asked by At

I want to pass json data that I get from an API into an array and display that information in my template and I don't know how to do that.

this error apears on my console :

enter image description here

my ts file :

this.api.getJoursFeries(year).subscribe(
      (data: feries[]) => {
        this.joursFeries = data;
        // console.log(data);
      }, (error: HttpErrorResponse) => {
        console.log(error);
      }
)

my service file :

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { feries } from '../models/feries';

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  private apiBaseUrl = 'https://calendrier.api.gouv.fr/jours-feries/metropole'

  constructor(private http: HttpClient) { }

  getJoursFeries(annee : number): Observable<feries[]> {
    return this.http.get<feries[]>(`${this.apiBaseUrl}/${annee}.json`);
  }
}
2

There are 2 answers

0
Charlie V On

The JSON response from https://calendrier.api.gouv.fr/jours-feries/metropole/2021.json is not an Array but a Javascript Object with different Key-Value pairs.

{
     "2021-01-01": "1er janvier",
     "2021-04-05": "Lundi de Pâques",
     "2021-05-01": "1er mai",
     "2021-05-08": "8 mai",
     "2021-05-13": "Ascension",
     "2021-05-24": "Lundi de Pentecôte",
     "2021-07-14": "14 juillet",
     "2021-08-15": "Assomption",
     "2021-11-01": "Toussaint",
     "2021-11-11": "11 novembre",
     "2021-12-25": "Jour de Noël" 
}

In your service you need to map the JSON object (from the server) to an Array (that you can use with *ngFor).

Let's assume the feries are defined as:

type feries = {
  fDate: string;
  fName: string;
};

then in your service you can change the code for getting the data into:

getJoursFeries(annee: number): Observable<feries[]> {
    return this.http.get<any>(`${this.apiBaseUrl}/${annee}.json`).pipe(
      map((val) => {
        let feriesList: feries[] = [];
        for (var key of Object.keys(val)) {
          feriesList.push({ fDate: key, fName: val[key] });
        }
        return feriesList;
      })
    );
  }

Can you share the feries type? Then I can update the answer properly.

0
Jordi Riera On

Assuming that you have already defined an interface that represents the objects given from the response, you have two ways to represent that data in the template.

The easiest way is to assign an array variable from the component to the array response from the subscription and then in the template you would use *ngFor directive to display the data

   //ts file
import { Component } from '@angular/core';
import {ApiService} from 'path/to/service'
import {Feries} from 'path/to/feriesModel'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'myClass';

  joursFeries: Feries[] = []

  constructor(private apiService: ApiService) {
  }

  ngOnInit() {
    apiService.getJoursFeries().subscribe(data => {
      this.joursFeries = data;
    })

  }
}

//html file

<div *ngFor="let ferie of joursFeries">
    <p>{{ferie.name}}</p>
  </div>

A more principled way would be to create a BehaviourSubject in your service then convert it to an Observable via .asObservable() Assign this service Observable to an Observable variable in your component.ts file and then use the ngFor with the observable with the async pipe. However this requieres some knowledge of the RxJS library and how to properly work with Observables. Let me know if you need further details for the solution