0

Im trying to display this information about weather cities, but im having trouble at the last moment, I think. The API is OpenWeatherMap and the call is based on the docs. I've checked this post, tried to follow its logic but my problem remains, data wont render, with the error "ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays."

This is my service:

export class WeatherService {

constructor(private http: HttpClient) { }

forecast: RootObject;

getForecast() {
  const url = 'http://api.openweathermap.org/data/2.5/forecast?lat=35&lon=139&APPID=ef48ddb3926ce0283de7291a09fd253e';
  return <Observable<RootObject[]>> this.http.get(url)
  .pipe(
      retry(3),
      catchError(this.handleError));
}

This is the generated interface:

export interface RootObject {
  coord: Coord;
  sys: Sys;
  weather: Weather[];
  main: Main;
  wind: Wind;
  rain: Rain;
  clouds: Clouds;
  dt: number;
  id: number;
  name: string;
  cod: number;
}

interface Clouds {
  all: number;
}

interface Rain {
  '3h': number;
}

interface Wind {
  speed: number;
  deg: number;
}

interface Main {
  temp: number;
  humidity: number;
  pressure: number;
  temp_min: number;
  temp_max: number;
}

interface Weather {
  id: number;
  main: string;
  description: string;
  icon: string;
}

interface Sys {
  country: string;
  sunrise: number;
  sunset: number;
}

interface Coord {
  lon: number;
  lat: number;
}

The component:

export class MainComponent implements OnInit {

foreCast: RootObject[];

  constructor(private weatherService: WeatherService) {
    this.getForecast();
   }

  ngOnInit() {
  }

getForecast() {
  this.weatherService.getForecast()
  .subscribe(data => {
    this.foreCast = data;
    console.log(this.foreCast);
  });
}

And the HTML:

<ul *ngFor="let wind of foreCast">


<li>{{wind.speed}}</li>

</ul>

This the log I get:

enter image description here

All the imports are in place, and the console.log show's me the retrieved object. What am I missing in this mapping?

0

3 Answers 3

0

As the error log says, it seems like you are iterating over an object and not an array. What does the console.log say?

I am assuming that you are not getting an array, but a object.

Another thing is the usage of the getForecast method. The httpClient always returns a Observable, you can only determine the type you expect:

getForecast():Observable<RootObject[]> {
  const url = 'http://api.openweathermap.org/data/2.5/forecast?lat=35&lon=139&APPID=ef48ddb3926ce0283de7291a09fd253e';
  return this.http.get<RootObject[]>(url)
  .pipe(
      retry(3),
      catchError(this.handleError));
}
Sign up to request clarification or add additional context in comments.

2 Comments

I've edited the answer with a pic. I know that I get an object, but i thought i was inserting that in object type array?
well, now i get this error: ReferenceError: map is not defined
0

I now had a deeper look into you rest api. Assuming that you want to list always the speed of the wind you have to do the following:

getForecast():Observable<RootObject[]> {
  const url = 'http://api.openweathermap.org/data/2.5/forecast?lat=35&lon=139&APPID=ef48ddb3926ce0283de7291a09fd253e';
  return this.http.get<RootObject[]>(url)
  .pipe(
      map(res => res.list)
      retry(3),
      catchError(this.handleError));
}

in your template:

<ul *ngFor="let obj of foreCast">
  <li>{{obj.wind.speed}}</li>
</ul>

5 Comments

wait, im having trouble with the map, i guess i miss an import
I've prepared an example: stackblitz.com/edit/angular-1qbdv6 copy the snippets, it will not work in stackblitz directly cause your api is not provided over a secured connection
thank you for the support, im sorry for the late reply, i was out of the office, im gonna try your example
wonderful, it works now...I dont know wich answer to vote, feel free to edit or delete any, and thanks again :)
well @fabi_k, your solution works, I get the data rendered, but im not using the interfaces, wich was the main purpose of this post...but thanks anyway
0

The solution was quite simple: it was all about targeting a nested object and initializing the model

Service.TS:

getForecast(): Observable<RootObject[]> {
    const url = 'http://api.openweathermap.org/data/2.5/forecast?lat=35&lon=139&APPID=ef48ddb3926ce0283de7291a09fd253e';
    return this.http.get<RootObject[]>(url)
    .pipe(
      retry(3),
      catchError(this.handleError));

  }

Component:

forecasts: RootObject[] = []; //Initialize

  constructor(private weatherService: WeatherService) {
    this.getForecast();
  }

  getForecast() {
    this.weatherService.getForecast()
      .subscribe(data => {
        this.forecasts = data;
        console.log(this.forecasts);
      });
  }

And the main problem, rendering the data:

<div class="container" >
  <ul *ngFor="let list of forecasts.list">
      <li>{{list.dt}}</li>
      </ul>
</div>

I was aiming not deep enough because the fetched data is a nested object

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.