I am using latest angular version 18.1.0 and want to use async pipe for an array of countries fetched from the backend using http client. But while using new angular feature of @for it give me error:
Type 'Country' must have a 'Symbol.iterator' method that returns an iterator.
My code is as follows country.component.html
<main>
<select name="countries" id="countries-selection">
@for (country of countries$ | async; track $index) {
<option value="{{country}}">{{ country }}</option>
}
</select>
</main>
country.component.ts
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
import { Country } from './country.model';
import { Observable, map } from 'rxjs';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-country',
standalone: true,
imports: [CommonModule],
templateUrl: './country.component.html',
styleUrl: './country.component.css'
})
export class CountryComponent {
countries$: Observable<Country>;
constructor(private httpClient: HttpClient) {
this.countries$ = this.httpClient.get('http://localhost:3000/countries').pipe(
map((response: any) => <Country> response.json()));
}
}
EDIT: I am getting following array from the server:
[
{
"id": "1",
"name": "Australia",
"isCurrent": true,
"timezone": "Asia/Karachi"
},
{
"id": "2",
"name": "Canada",
"isCurrent": true,
"timezone": "Asia/Karachi"
},
{
"id": "3",
"name": "Finland",
"isCurrent": false,
"timezone": "Europe/Tallinn"
}
]
What could be the possible solution if I want to use rxjs and not JS async/await for fetching the countries?
@for
iterates over arrays. According to your types, countries$
is an Observable of a Country
object, which Angular doesn't accept to iterate over. Just add []
to indicate that it's a list of Country
objects:
export class CountryComponent {
countries$: Observable<Country[]>;
constructor(private httpClient: HttpClient) {
this.countries$ = this.httpClient.get<Country[]>('http://localhost:3000/countries');
}
}
One additional note, calling response.json()
is not something which Angular's HTTP client supports. It will parse to JSON by default, so probably you can just skip this part.