javaangularkey-valueangular-maps

Java / Angular: keyvalue pipe doesn't show data sent from backend


I'am trying to set up an app in which the backend receives data from an api and proceeds it to the frontend. The api is https://www.travel-advisory.info/api

Long story short: For some reason, I seem to receive the data in the frontend, but I cannot display it in a table or list.

As a first step, I want to get all data, and as I eventually want to make it persistent I am already using Spring with the get method. My controller in Java:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.savetravel.SaveTravel.TravelWarning.TravelWarningObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;


import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/gettravelwarnings")
public class TravelWarningController {
    
    @GetMapping("/alltw")
    public TravelWarningObject getAllTravelWarnings()
            throws JsonMappingException, JsonProcessingException {
        
        RestTemplate restTemplate = new RestTemplate();
        TravelWarningObject allTravelWarnings = new TravelWarningObject();
        
        ResponseEntity<TravelWarningObject> responseEntity = restTemplate.getForEntity(
                "https://www.travel-advisory.info/api", TravelWarningObject.class);
        allTravelWarnings = responseEntity.getBody();
    
        return allTravelWarnings;
                
    }
}

My Model in Java:

package com.savetravel.SaveTravel.TravelWarning;

import java.util.HashMap;

public class TravelWarningObject {

    private Api_status api_status;
    private HashMap<String, CountryCode> data;

public TravelWarningObject () {
    
}

public HashMap<String, CountryCode> getData() {
    return data;
}

public void setData(HashMap<String, CountryCode> data) {
    this.data = data;
}

public Api_status getApi_status() {
    return api_status;
}

public void setApi_status(Api_status api_status) {
    this.api_status = api_status;
}

}

and

package com.savetravel.SaveTravel.TravelWarning;


public class CountryCode {

    private String iso_alpha_2;
    private String name;
    private String continent; 
    private Advisory advisory;
    
    public CountryCode() {
        
    }
    
    public CountryCode(String iso_alpha_2, String name, String continent,
            com.savetravel.SaveTravel.TravelWarning.Advisory advisory) {
        super();
        this.iso_alpha_2 = iso_alpha_2;
        this.name = name;
        this.continent = continent;
        this.advisory = advisory;
    }

    public String getIso_alpha_2() {
        return iso_alpha_2;
    }

    public void setIso_alpha_2(String iso_alpha_2) {
        this.iso_alpha_2 =  iso_alpha_2;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContinent() {
        return continent;
    }

    public void setContinent(String continent) {
        this.continent = continent;
    }

    public Advisory getAdvisory() {
        return advisory;
    }

    public void setAdvisory(Advisory advisory) {
        this.advisory = advisory;
    }
            
}

Well...and using the same pattern I have also the objects "Advisory.java", "Api_status.java", "Reply.java","Request.java". In my Angular project, I have, analogously, the same Models in .ts . Additionally, I have this service:

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

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

  constructor(private http: HttpClient) { }

rootApiPath:string = "http://localhost:8080/gettravelwarnings"


public getAllTWs(): Observable<TravelWarningObject> {
return this.http.get<TravelWarningObject>(this.rootApiPath + "/alltw");

}
}

..and this component:

import { Component, OnInit } from '@angular/core';
import { CountryDataServiceService } from '../service/country-data-service.service';
import { TravelWarningObject } from '../Models/TravelWarningObject';
import { CountryCode } from '../Models/CountryCode';

@Component({
  selector: 'app-all-travel-warnings',
  templateUrl: './all-travel-warnings.component.html',
  styleUrls: ['./all-travel-warnings.component.css']
})
export class AllTravelWarningsComponent implements OnInit {


travelWarningObject = new TravelWarningObject;

  constructor(private countryDataService: CountryDataServiceService) { }

  ngOnInit(): void {

    this.countryDataService.getAllTWs().subscribe(fetchedTWO => (this.travelWarningObject = fetchedTWO));
           
  }

}

and in html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

<table border="1">

<thead>
    <tr>
<th>Country</th>
<th>Code</th>
</tr>
</thead>
    <tbody>
    <tr *ngFor = "let value of travelWarningObject.data | keyvalue">
        <td>{{value.name}}</td>
        <td>{{value.iso_alpha2}}</td>
    </tr>
</tbody>
</table>


{{travelWarningObject | json }}
<br />
--------
<br />
{{travelWarningObject.data | json }}
<br />

</body>
</html>

The funny thing now is that the json pipe shows perfectly all the data from the api when I run Spring Boot and ng serve. However, there is no data in the table. Still, and thats the most bewildering thing to me, a table is shown in the browser on localhost:4200 which has the right number of rows but no content.

I don't receie any error message whatsoever, neither in the dev tools of my browser nor in the bash.

Thanks for your help, if you need any kind of additional information I'd be happy to provide it!

Linux version 4.8.0-53-generic (buildd@lgw01-56) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #56~16.04.1-Ubuntu SMP Tue May 16 01:18:56 UTC 2017
------
openjdk version "13.0.1-BellSoft" 2019-10-15
------
Angular CLI: 9.0.6
Node: 10.22.0


Solution

  • As name suggests Keyvalue,it returns key and value. Use it like below get your result.

    <tr *ngFor = "let item of travelWarningObject.data | keyvalue">
        <td>{{item.key}}</td>
        <td>{{item.value.iso_alpha2}}</td>
    </tr>