A guide on extracting JSON Data and populating an Array in Angular 7

I have a JSON file stored locally containing various data. My goal is to extract the CityCodes specifically and store them in an array. Then, I plan to send these CityCodes as part of the OpenWeatherMap API request. Finally, I aim to display all the weather records within the HTML file.

CityData.json:

{
    "List": [
    {
    "CityCode": "1248991",
    "CityName": "Colombo",
    "Temp": "33.0",
    "Status": "Clouds"
    },
    {
    "CityCode": "1850147",
    "CityName": "Tokyo",
    "Temp": "8.6",
    "Status": "Clear"
    },
    {
    "CityCode": "2644210",
    "CityName": "Liverpool",
    "Temp": "16.5",
    "Status": "Rain"
    }
]

Weather.Service.ts :

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

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

  apiKey = '9402da6bd74c395f71604c624cc2b231';
  url;

  constructor(private http:HttpClient) { 
    this.url='http://api.openweathermap.org/data/2.5/group?id=';  //API GET URL

  }

  getWeather(cityCode){
    return this.http.get(this.url+cityCode+'&units=metric&appid='+this.apiKey);
  }

}

home.component.ts :

Currently passing the area code manually but looking to automate this with the CityCodes fetched from the JSON file.

import { Component, OnInit } from '@angular/core';
import { WeatherService } from "../shared/weather.service";
// import { weather} from "../shared/weather.model";

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

  location={    
    code: '1248991'  //Passing Area Code Manually
  };

  public weather: any;

  constructor(private weatherService:WeatherService) {

  }

  ngOnInit() {
    this.weatherService.getWeather(this.location.code).subscribe((Response:any)=>{
      console.log(Response);
      this.weather = Response.list;
    })
  }

}

home.component.html :

<table class="table table-hover">
          <thead>
            <th>City</th>
            <th>City Code</th>
            <th>Temperature</th>
            <th>Description</th>            
          </thead>
          <tbody>
            <tr *ngFor="let weather of weather">
              <td>{{weather.name}}</td>
              <td>{{weather.id}}</td>
              <td>{{weather.main.temp}}</td>
              <td>{{weather.weather[0].description}}</td>              
            </tr>
          </tbody>
        </table>

Answer №1

I successfully resolved the issue by storing the JSON Response in an Array.

Home.component.ts

  public data: any;
  public weatherData: any;

  constructor(private weatherService:WeatherService) {

  }

  ngOnInit() {   
    this.weatherService.getJsonData('./assets/City.json').subscribe(response => {
            this.data = response;         //Retrieving JSON Data
            this.fetchWeatherList();    //Calling FetchWeatherList Function
      }); 
  }

  fetchWeatherList(){
    if (this.data) {

      // console.log(this.data);

      const dataList = this.data.List;
      let tempArray : any = [];

      for (let item of dataList) {
        this.weatherService.getWeather(item.CityCode).subscribe((weatherResponse: any) => {
          tempArray.push(weatherResponse.list[0]);         //Adding Response to Array
        })        
      }
      console.log(tempArray)
      this.weatherData = tempArray;   //Assigning Array to Weather Data Constant
    }
  }

Answer №2

Begin by fetching JSON data through an HTTP get request and utilize the forkJoin method to concurrently retrieve weather information from an API, similar to Promise.all.

// Include in service
get(url){
    return this.http.get(url);
}

// Component
ngOnInit() {
    this.weatherService.get('url of json file').subscribe((cities:any)=>{
        const {List} = cities;
        const obsArr = List.map(location => this.weatherService.getWeather(location.CityCode));
        forkJoin(obsArr).subscribe(  => { // import forkJoin
            console.log(val)
            this.weatherlist = val; // adjust as needed based on response
        }); 
    })
  }

// HTML
<tr *ngFor="let weather of weatherlist">
    <td>{{weather.name}}</td>
    <td>{{weather.id}}</td>
    <td>{{weather.main.temp}}</td>
    <td>{{weather.description}}</td>              
</tr>

Answer №3

To update the weather service, modify it to accept the local JSON file path and read its content.

  public getJsonData(filePath: string){
        return this.http.get(filePath);
  }

In your component, implement the following:

  export class HomeComponent implements OnInit {

  public data: any;
  public weather: any;

  constructor(private weatherService: WeatherService) {}

  ngOnInit() {   
    this.weatherService.getJsonData('./data.json').subscribe(data => {
            this.data = data;
            this.getWeatherList();
      }); 
  }

  getWeatherList(){
    if (this.data) {
      const dataList = JSON.parse(this.data).List;
      for (let temp of dataList) {
        this.weatherService.getWeather(temp.CityCode).subscribe((Response: any) => {
          console.log(Response);
          if (Response && Response.list) {
            this.weather.push(Response.list[0]);
          }
        })
      }
    }
  }
}

For a working example, please refer to this StackBlitz link. Note that file data is hardcoded in the example as StackBlitz cannot read local files.

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

How to prevent right-clicking on an entire website using Angular, not just specific pages

I have been searching for a solution to disable right-click on my entire Angular 2+ application, but all I can find are solutions that only work for specific components such as, <someSelector appDisableRightClick></someSelector> Where "someSel ...

Typescript: object containing at least one property with the type T assigned

Is there a method to write the HasNumber interface in Typescript without receiving an error due to the fact that the HasNumberAndString interface includes a property that is not of type number? I am looking for a way to require the HasNumberAndString int ...

Understanding and handling live JSON data feed on iOS devices

Struggling with understanding JSON for my current app development project. The app involves using a NSInputStream connected to a server through CFStreamCreatePairWithSocketToHost. The server is sending JSON objects asynchronously to the app. When reactin ...

Is there a way to tally up the overall count of digits in a number using TypeScript?

Creating a number variable named temp in TypeScript: temp: number = 0.123; Is there a way to determine the total count of digits in a number (in this case, it's 3)? ...

The mat-slide-toggle updates the values for all products, with each value being unique

In my app, I am using Material slide-toggle to control the activation status of products. However, I am facing the following issues: Whenever I toggle one product, it affects the values of all other products as well. The displayed value does not match t ...

Produce a single value using the EventEmitter in Angular

There are four values of products (A,B,C,D) that need to be passed to a parent component in Angular when a user clicks on them. However, despite attempting to use EventEmitter.emit to pass the value clicked on, only the first value 'A' is always ...

Getting a string from JSON using Javascript

I am trying to retrieve a specific skill from a variable: const skillsData = [ { name: "React", value: 390 }, { name: "CSS", value: 1200 }, { name: "JavsScript", value: 540 }, { name: "HTML", value: 1900 }, ...

Manipulating JSON data by accessing and updating a specific property with the help of a variable

Let's dive into the complexities of my current project. I am delving deep into U.S. Census bureau information, specifically focusing on a snippet of data from an object that looks like this: (Remember, this is only a portion of the complete object.) ...

Using TypeScript and Node.js with Express; I encountered an issue where it was not possible to set a class property of a controller using

I have a Node application using Express that incorporates TypeScript with Babel. Recently, I attempted to create a UserController which includes a private property called _user: User and initialize it within the class constructor. However, every time I ru ...

What is the best way to divide a single file Angular module into separate client-side, server-side, and shared files?

When working on an Angular 4 project scaffolded by dotnet-cli, the module artefact is split into three files: one for shared components, one for server-related components, and one for client-specific components. These files are named as follows: <module ...

The specified type '{ state: any; dispatch: React.Dispatch<{ type: string; value: any; }>; }' is not compatible with the expected type

I've been working on a UI layout that includes checkboxes on the left, a data table on the right, and a drop zone box. The aim is to keep the table data updated whenever a new file is dropped, and also filter the data based on checkbox selection. I ma ...

Is it possible to nest enums within enums in TypeScript programming?

enum TYPES { CODE = 1, TEXT, IMAGE, VIDEO } enum ALL_TYPES { CODE = 1, TEXT, IMAGE, VIDEO, NONE } Is there a way to incorporate the TYPES enum into the ALL_TYPES enum? ...

Troubleshooting the excessive time taken for Angular Material tree re-rendering

I am currently using mat-tree with large data sets in child nodes retrieved from an API call, with each child node containing around 3k records. My approach involves updating the dataSource by adding the children from the API under the existing dataSource ...

Unexpected error encountered in Angular 2 beta: IE 10 displays 'Potentially unhandled rejection [3] SyntaxError: Expected'

Question regarding Angular 2 Beta: I am starting off with a general overview in the hopes that this issue is already recognized, and I simply overlooked something during my research. Initially, when Angular 2 Beta.0 was released, I managed to run a basic m ...

Guide to creating varying component sizes using ReactJS and Styled Components

Is it possible to add variation to my button based on the prop 'size' being set to either 'small' or 'medium'? interface Props { size?: 'medium' | 'small'; } How can I adjust the size of the component us ...

What sets apart the ? operator from incorporating undefined in the type declaration?

Can you explain the distinctions among these options? type A = {a?: string} type A = {a: string | undefined} type A = {a?: string | undefined} In what scenarios would one be preferred over the others? For more information, visit: https://github.com/mic ...

The enigmatic occurrence of TypeScript decorators: when a decorator parameter mysteriously transforms into undefined in a particular scenario

I have been working on developing my own Object-Relational Mapping (ORM) system and I encountered an interesting issue in TypeScript that I am trying to understand. If anyone can provide some insight or clarification on this matter, it would be greatly app ...

What is the best way to remove linear-gradient effects applied by a dark mode theme?

Why does MUI add random gradients to components, like in dark mode? Is there a way to disable this feature because it doesn't match the exact color I expected for my custom theme... My Theme Options export const themeOptions: ThemeOptions = { palette ...

Using Angular 2: Implementing Router into myExceptionHandler

Within my app.module.ts, I've set up the following code: @NgModule({ declarations: [ AppComponent, ], imports: [ BrowserModule, FormsModule, ReactiveFormsModule, HttpModule ], providers: [ ...

Executing RxJS calls in a sequential manner while allowing inner calls to operate in

I want to achieve a scenario using rxjs where a group of http calls are made with the value returned from a previous call. The inner calls should run in parallel, while still being able to return the value from the first call as soon as it's available ...