Search code examples
javascriptangulartypescriptservicemean-stack

Issues loading in json data from API in Angular


I am working on a project where we are building a website using the MEAN stack. I am currently working on the front end and am attempting to read in data from an API and storing that data within an array that I can then access and use. I am running into a very odd issue.

I am aiming to load in an array of data containing latitude and longitude coordinates of all the countries in the world.

I have a service that looks like this:

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

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

  REST_API_SERVER = 'http://localhost:3000/countries/getCountries';

  constructor(private httpClient: HttpClient) { }

  getCountryData() : Observable<Country[]>{

    return this.httpClient.get<Country[]>(this.REST_API_SERVER);
      
  }
}

Where Country is a class with certain attributes.

I am then accessing this function and using it by doing the following in my component.ts file:

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef, HostListener, Host } from '@angular/core';
import { Country } from '../models/country';
import { DataService } from '../services/data.service';

export class GlobeComponent implements AfterViewInit {

  listOfCountries!: Country[];

  constructor(private countryService : DataService) {
  }

ngOnInit() {
   
    this.countryService.getCountryData().subscribe((countries) => {
      this.listOfCountries = countries;
    });
} 

I then try to access listOfCountries but am unable to. For example, if I say:

 for (let i = 0; i < this.listOfCountries.length; i++) 

I get the following error:

ERROR TypeError: Cannot read property 'length' of undefined

However, if in ngOnInit() function I include the following line:

console.log("Country printed in ngOnInit : " + this.listOfCountries[0].Entity);

It magically starts working. BUT... I get a new error:

ERROR TypeError: Cannot read property '0' of undefined at GlobeComponent.ngOnInit

I am really confused as to why this is happening. Why does console.log populate the array? But why does it continue to claim that the array is undefined even though it is working? After including the console.log, I can access and use the array as normal. But I do not want to keep this console.log, so any help as to where I am going wrong would be much appreciated!


Solution

  • Okay, referring to your provided code here, you have 2 options:

    Option 1

    Create a method that is called when the value is present. Do not rely on AfterViewInit.

    listOfCountries: Country[] = [];
    
    ngOnInit() {
       this.countryService.getCountryData().subscribe((countries) => {
         this.listOfCountries = countries;
    
         this.initDependencies();
       });
     }
    
     initDependencies() {
       this.setScene();
       this.setCamera();
       this.setRenderer();
       this.setControls();
    
       this.createLightGroup();
       this.createGlobe();
    
       this.animate();
       this.setAllPoints(this.currentYear);
     }
    

    Option 2

    Only call this.setAllPoints(this.currentYear); separately, when the value is present.

    listOfCountries: Country[] = [];
    
    ngOnInit() {
       this.countryService.getCountryData().subscribe((countries) => {
         this.listOfCountries = countries;
         
         this.setAllPoints(this.currentYear);
       });
    }
    
    ngAfterViewInit() {
       this.setScene();
       this.setCamera();
       this.setRenderer();
       this.setControls();
    
       this.createLightGroup();
       this.createGlobe();
    
       this.animate();
    }