-1

I am now building my front-end now on Angular and for the life of me, I cannot see what is causing this error. I am using Node.js as my backend. Below is my code.

country.ts

export class Country {
  id?: string;
  name?: string;
  icon?: string;
  imageFlag?: string;
}

countries.services.ts

export class CountriesService {
  constructor(private http: HttpClient) {}

  getCountries(): Observable<Country[]> {
    return this.http.get<Country[]>('http://127.0.0.1:3300/api/v1/countries/');
  }
}

countries-list.component.ts

export class CountriesListComponent implements OnInit {
  countries: Country[] = [];

  constructor(private countriesService: CountriesService) {}

  ngOnInit(): void {
    this.countriesService.getCountries().subscribe((amazwe) => {
      this.countries = amazwe;
      console.log(amazwe);
    });
  }
}

My console on console.log(amazwe) depicts the below

{
    "status": "success",
    "results": 7,
    "data": {
        "data": [
            {
                "_id": "61c4827a69a96679469adac2",
                "name": "Botswana",
                "icon": "Safari iCON",
                "imageFlag": "Botswana Flag",
                "__v": 0,
                "id": "61c4827a69a96679469adac2"
            },
            {
                "_id": "61c482ab69a96679469adac4",
                "name": "South Africa",
                "icon": "Safari iCON",
                "imageFlag": "South Africa Flag",
                "__v": 0,
                "id": "61c482ab69a96679469adac4"
            },
            {
                "_id": "61c482c369a96679469adac6",
                "name": "Namibia",
                "icon": "Safari iCON",
                "imageFlag": "Namibia Flag",
                "__v": 0,
                "id": "61c482c369a96679469adac6"
            },
            {
                "_id": "61c482f569a96679469adac8",
                "name": "Mozambique",
                "icon": "Safari iCON",
                "imageFlag": "Mozambique Flag",
                "__v": 0,
                "id": "61c482f569a96679469adac8"
            },
            {
                "_id": "61c4831769a96679469adaca",
                "name": "Zimbabwe",
                "icon": "Safari iCON",
                "imageFlag": "Zimbabwe Flag",
                "__v": 0,
                "id": "61c4831769a96679469adaca"
            },
            {
                "_id": "61c4832f69a96679469adacc",
                "name": "Zambia",
                "icon": "Safari iCON",
                "imageFlag": "Zambia Flag",
                "__v": 0,
                "id": "61c4832f69a96679469adacc"
            },
            {
                "_id": "61c4836369a96679469adace",
                "name": "Tanzania",
                "icon": "Safari iCON",
                "imageFlag": "Tanzania Flag",
                "__v": 0,
                "id": "61c4836369a96679469adace"
            }
        ]
    }
}
Yong Shun
  • 35,286
  • 4
  • 24
  • 46
tourafrika
  • 15
  • 6

2 Answers2

2

Your response data to class/interface is as below:

export interface ICountryListResponse {
  status: string;
  results: number;
  data: { data: Country[] };
}

Modify your CountriesService.getCountries() to expect received ICountryListResponse data response and next with .pipe(map) to return the result as Observable<Country[]>.

countries.services.ts

import { map } from 'rxjs/operators';

getCountries(): Observable<Country[]> {
  return this.http
    .get<ICountryListResponse>('http://127.0.0.1:3300/api/v1/countries/')
    .pipe(map((response: ICountryListResponse) => response.data.data));
}

Sample Demo on StackBlitz

Yong Shun
  • 35,286
  • 4
  • 24
  • 46
  • Your solution introduces 3 errors. Error 1. Module '"@tourafrika/tours"' has no exported member 'Country' in the countries-list.component.ts file points to import { CountriesService, Country } from '@tourafrika/tours'; I do export my country.ts file in my index.ts file as per this code export * from './lib/models/country'; I have an @NgModule - exports = [ShellComponent, SidebarComponent, CountriesListComponent] Error 2: In country.ts Cannot find name 'Country'. data: { data: Country[] }; Error 3: In countries.service.ts Cannot find name 'Country'. getCountries(): Observable { – tourafrika Jan 16 '22 at 08:08
  • Did you import Country class to each class that is needed? And please create a minimal reproducible example on [StackBlitz](https://stackblitz.com), for easier to debug. Thanks. – Yong Shun Jan 16 '22 at 08:18
  • 1
    Thanks Yong. All is working now! I had replaced my initial Country Class with your ICountryListResponse interface. Somewhere in my training I was instructed that you can use the interface or class declaration in creating your model and in my case that would be country.ts model. So I rushed to replace my existing Country Class with your ICountryListResponse interface. On reviewing my code I picked my mistake and all is working fine now. A million thanks. This is an excellent learning curve for me. – tourafrika Jan 16 '22 at 08:56
1

It helps to use a JSON formatter (like this one: https://codebeautify.org/jsonviewer) to get a better look at the data:

{
  "status": "success",
  "results": 7,
  "data": {
    "data": [
      {
        "_id": "61c4827a69a96679469adac2",
        "name": "Botswana",
        "icon": "Safari iCON",
        "imageFlag": "Botswana Flag",
        "__v": 0,
        "id": "61c4827a69a96679469adac2"
      },
      {
        "_id": "61c482ab69a96679469adac4",
        "name": "South Africa",
        "icon": "Safari iCON",
        "imageFlag": "South Africa Flag",
        "__v": 0,
        "id": "61c482ab69a96679469adac4"
      },
      {
        "_id": "61c482c369a96679469adac6",
        "name": "Namibia",
        "icon": "Safari iCON",
        "imageFlag": "Namibia Flag",
        "__v": 0,
        "id": "61c482c369a96679469adac6"
      },
      {
        "_id": "61c482f569a96679469adac8",
        "name": "Mozambique",
        "icon": "Safari iCON",
        "imageFlag": "Mozambique Flag",
        "__v": 0,
        "id": "61c482f569a96679469adac8"
      },
      {
        "_id": "61c4831769a96679469adaca",
        "name": "Zimbabwe",
        "icon": "Safari iCON",
        "imageFlag": "Zimbabwe Flag",
        "__v": 0,
        "id": "61c4831769a96679469adaca"
      },
      {
        "_id": "61c4832f69a96679469adacc",
        "name": "Zambia",
        "icon": "Safari iCON",
        "imageFlag": "Zambia Flag",
        "__v": 0,
        "id": "61c4832f69a96679469adacc"
      },
      {
        "_id": "61c4836369a96679469adace",
        "name": "Tanzania",
        "icon": "Safari iCON",
        "imageFlag": "Tanzania Flag",
        "__v": 0,
        "id": "61c4836369a96679469adace"
      }
    ]
  }
}

It looks like you're getting the data back that you want, but it just has a wrapper around it.

this.countries = amazwe.data.data;

...would give you the result I suspect you're looking for, but you'd have to alter the typing of the return value to handle this.

kshetline
  • 12,547
  • 4
  • 37
  • 73
  • Thanks for the heads up on use of the JSON formatter. This is my first post and still figuring out appropriate button options/use. – tourafrika Jan 16 '22 at 08:13
  • Yes that is correct, the data on the console.log(amazwe) is indeed the data I want reflected on my front-end. Changing my code to this.countries = amazwe.data.data; introduces a new error that states Property 'data' does not exist on type 'Country[]'. 16 this.countries = amazwe.data.data; This error is in my countries-list.component.ts ~~~~ – tourafrika Jan 16 '22 at 08:21
  • Yes, as I said, the type definition needs to be updated to match the data structure you're getting back. – kshetline Jan 16 '22 at 08:36
  • Thanks kshetline. Your solution does work also. – tourafrika Jan 16 '22 at 09:49