0

I am trying to fetch data from a JSON file and display that data in the form

JSON FILE Link: https://raw.githubusercontent.com/datameet/railways/master/trains.json

I am trying with the below code. But it returns following error in fetchdata.component.ts file:

Property 'json' does not exist on type 'Object'.

fetchdata.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-fetchdata',
  templateUrl: './fetchdata.component.html',
  styleUrls: ['./fetchdata.component.css']
})

export class FetchdataComponent implements OnInit {

  private _trainUrl = "https://raw.githubusercontent.com/datameet/railways/master/trains.json
";
  items : any;
  constructor(private http:HttpClient) {
    this.http.get( this._trainUrl)
      .subscribe(res => this.items = res.json());
    console.log(this.items);
  }

  ngOnInit() {
  }

}

fetchdata.component.html

<select>
  <option  *ngFor="let item of items" [value]="item.properties.from_station_name">{{item.properties.from_station_name}}</option>
</select>

Please help.

4
  • Try console.log(res)? It is probably already returning the response body itself. You only need to use .json() if you are using the native fetch api Commented Apr 23, 2019 at 5:09
  • It is now giving another error: "Cannot find name 'res'." Commented Apr 23, 2019 at 5:11
  • I see.. I guess none of the answers below solves your problem too? Commented Apr 23, 2019 at 5:22
  • hi, @Tony7931 Please check the API response. you can get the object in response and that object pass into *ngFor that is not valid and also you can directly assign res to this.items. Like this.items = res Commented Apr 23, 2019 at 5:27

5 Answers 5

3

The response probably isn't what you think. I suggest you console.log() the response of your query to see what it actually looks like:

    items : any;
    constructor(private http:HttpClient) {
      this.http.get( this._trainUrl)
        .subscribe(res => {
          this.items = res.features; 
          console.log("Response", res);
          console.log(res.features)
        });
    }

You'll see that you actually get something like this in your console:

{type: "FeatureCollection", features: Array(5208)}
features: (5208) [{…}, …]
type: "FeatureCollection"
__proto__: Object

So you can assign your items to the features key as that's what you really need:

 constructor(private http:HttpClient) {
      this.http.get( this._trainUrl)
        .subscribe(res => {
          this.items = res["features"]; 
        });
    }

Then your select options should show up.

Just letting you know, this isn't the perfect way to do it but it works fine for a small example like this. I suggest you look into creating a service for any request in the future (doing it in the constructor isn't the best way) and have a look at the RxJS library

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. It is working and thanks for the suggestion, I will have a look at RxJS Library.
1

There is a difference between Angular's Http and HttpClient module and they are also exported differently.

  1. Http -> is the core module which requires the user to call res.json(). This was common prior to Angular version 4.0.

  2. HttpClient -> is new module since version 4.0. It defaults the communication to json and hence you don't need to call res.json() explicitly.

In short, changing from res.json() to just res will fix the issue for you.

i.e this.items = res; should be fine.

Also, as a good practice use the ngOnInit lifecycle method instead of the constructor to make any Http calls.

2 Comments

I am getting this error in Chrome Console and it is not showing any data in Select: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays. I have written this: .subscribe(res => this.items = res); console.log(this.items);
It is because the trains.json url you are calling is returning a json object instead of array. And you are probably trying to iterate on it in your template using ngFor. Check the correct property and its type which you are assigning to the select component.
0

Why do you do this.items = res.json()? Why not just this.items = res? res should already hold the JSON object returned from the GET request. If it is indeed a string try this.items = JSON.parse(res).

Comments

0

Can you try :

private _trainUrl = "https://raw.githubusercontent.com/datameet/railways/master/trains.json";
  items : any;
constructor(private http:HttpClient) {}


  ngOnInit() {
    this.http.get( this._trainUrl).subscribe(res => {
      this.items = res;
      console.log(this.items);
    });
  }

1 Comment

It is working but partly. It is showing the JSON data in the console but not in Select. It is giving this error in console: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
0

You don't need to call .json() function in case you doing plain this.http.get. Angular does that for you. Simply do this.items = res. That will do the trick.

UPD: your JSON object is not an array itself. You as well need to update your template in the following way:

<select>
  <option  *ngFor="let item of items.features" [value]="item.properties.from_station_name">{{item.properties.from_station_name}}</option>
</select>

3 Comments

Are you suggesting to do this: items : any; res: any; constructor(private http:HttpClient) { this.http.get( this._trainUrl) .subscribe(res => this.items = res); console.log(this.res); }
Just change this.items = res.json() to this.items = res in the code you've provided. console.log(items) will return undefined in your example, since http.get is async operation.
Now I am getting this error in Chrome Console and it is not showing any data in Select: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.