Troubles encountered while fetching JSON data from an API in Angular

Currently, I am in the process of developing a website using the MEAN stack for a project. My focus is on handling the front end operations, specifically on retrieving and storing data from an API into an array for future use. However, I seem to be encountering a peculiar issue.

My goal is to import an array that contains latitude and longitude coordinates for all countries worldwide.

The service I have created 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);
      
  }
}

In this code snippet, Country represents a class with specific attributes.

To utilize this function, I call it within my component.ts file as shown below:

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;
    });
} 

Although, when attempting to access listOfCountries, I encounter difficulties. For instance, the error message displays:

ERROR TypeError: Cannot read property 'length' of undefined

Interestingly, by adding a console.log statement within the ngOnInit() function:

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

It seems to start functioning correctly. Yet, now a new error arises:

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

This situation has left me puzzled. Why does the console.log statement populate the array, but the error persists regarding its undefined status? Despite the console.log workaround enabling normal array access and utilization, I prefer not to use it. Any advice on where my mistake lies would be highly appreciated!

Answer №1

Hey there! Taking a look at the code snippet you shared here, I can suggest two approaches:

Approach 1

Develop a method that triggers when the value is available, rather than relying 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);
 }

Approach 2

Call

this.setAllPoints(this.currentYear);
only after the value is available.

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();
}

Answer №2

The error occurs consistently in both scenarios.

This issue arises because the listOfCountries variable is initialized with an empty value, and it will only be populated once the subscription is triggered (typically after a response from the countryService).

To address this, you can either set a default value like listOfCountries: Country[] = []; or ensure that listOfCountries is indeed an array before attempting to access its values.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Verify if the text field is currently blank or has content before applying attributes

How can I disable one text box if another specific text box is filled within a div containing multiple text boxes? For example: When I enter text in textbox(4), I want to automatically disable textbox(1). And if I remove the text from textbox(4), I want t ...

Confirming the HTML5 input type of numerical values

I have a requirement to display 2 different validation messages for the input type shown below <input type="number" step="1" formControlName="Ordinal" /> Within my reactive forms setup, I have a formGroup structured like this formBuilder.group({ ...

A job with the title "..getProjectMetadata" is not found, causing an unhandled exception

Every time I try to run my Application, I encounter the following error: **[error] Error: Job name "..getProjectMetadata" does not exist.** at Observable._subscribe (/Users/vasil/KSS/kssfrontend/node_modules/@angular-devkit/core/src/experimental/jobs ...

In Vue firebase, ensure that the prop is only passed down after it has been

I am facing an issue where I need to pass down the Firebase user as a prop from the root component to my child components. I managed to achieve this by passing the user to my router. However, the problem arises when I wrap my new Vue instance in an onAuthS ...

Generate a new array of objects by cloning an existing array of objects with placeholder values

I am looking to transform an array of objects into another array of objects in order to generate a graph. Below is the array I am using to determine the position of each object within the new object. let uniqueSkills = ['Using', 'Analyzing ...

Encountering compilation errors with TypeScript files in Angular 2 while using Visual Studio 2017

Currently, I am in the process of developing an Angular 2 application Here is a snippet of the TypeScript code that I have written: import { Component } from 'angular2/core'; @Component({ selector: 'my-app', template: ' &l ...

Insert a fresh item to the end of the scrollable container

My goal is to dynamically add a div to the bottom of another div by using a JavaScript button click event. However, I have encountered an issue where once the outer container reaches its maximum height, the list no longer scrolls to the bottom after adding ...

Changing a date format in typescript: Here is how you can easily convert a date from one

Using React with Typescript: I am currently working with a date picker from material-ui version 5. The date picker requires the date value to be in the format "yyyy-MM-dd". However, the API returns a Date object in the format "2022-01-12T00:00:00.000+00:0 ...

Having trouble with rendering an OBJ file in threejs

It appears that some faces are missing from the obj file, resulting in improper rendering. The same object viewed in an online viewer shows all faces and parts rendered correctly. https://i.sstatic.net/tI3kb.jpg Below is the image I am trying to render on ...

Switching JSON data when clicked in Angular 2

Looking for a way to dynamically switch between different data sets in JSON upon user interaction with UI buttons. I am utilizing Angular 2 framework for this task. The HTML structure is as follows: <button type="button" (click)="changeOdds('odds ...

Creating a React.js NavBar: Can we refer to another component's HTML code? (Exploring the idea of a navigation bar that links to components within the same route)

My goal is to create a navbar for my personal website application that references different content sections (such as About, Skills, etc.) all on a single page route. However, I am running into some challenges. I can easily reference markup with ids/classe ...

How to ensure Service is loaded before App Component in Angular 6?

My Data service is responsible for fetching the JSON Object value, however all components load before the data service finishes loading. This results in undefined values when I call the service method from components. ...

ajax requests getting blocked after doPostBack

When a user clicks on an anchor tag, I am prompting them to download a file. In the onclick event, I am using __doPostBack to perform a partial page postback and return the downloadable file to the user. The issue I am encountering is that if the file is ...

Calculate averages of an array and show them when the page loads using Vue

In my coding project, there is an array named products that follows this specific structure: { "_id": "150", "name": "Milk", "description": "Skimmed", "price": "10", "ratings": [ ...

Meteor: dynamic approach to assigning array values in Spacebars

It's hard to put this into words... I have a collection with an array, and as I iterate through it, I've been setting colors.[0].imageLink without changing the [0]. Now, I want this to be dynamic based on the value of a function (in this case, th ...

Is sending a stream to a variable the best option, or could there be another solution

Is there a way to pipe stream data to a variable? The writable stream examples mentioned in this documentation include: HTTP requests on the client side HTTP responses on the server side Zlib streams Crypto streams TCP sockets Child process stdin Process ...

The order of CSS precedence shifts even when the class sequence is the same

In my development setup, I have a react component that is embedded within two distinct applications each with their own webpack configurations. Within the component, I am utilizing a FontAwesome icon using the react-fontawesome library: <FontAwesom ...

Looking to verify characters, numbers, and special characters with jQuery's regular expression feature?

Currently, I am facing a challenge in validating the password field to allow characters, numbers, and special characters. It is essential that the password consists of exactly 8 characters. Despite searching online for a solution, I have been unsuccessful ...

When selecting an input within a div, the Angular onblur function is behaving erratically

How can I prevent the div from closing when I click on an input inside it after setting a tabindex to the div and closing it on blur? Solution for app.component.html: <button (click)="openToggle('toggle1')">Toggle 1</button> ...

When running the command `npm start`, an error message is generated

Hey everyone, I've been trying to learn some basic AngularJS 2.0 skills through a tutorial. Unfortunately, when I tried running the command npm run start, it didn't work as expected. I'm currently using Git Bash on Windows 10 OS. If you hav ...