Reputation: 35
In my angular application I am using an api to fetch data about a selected country.
I am not able to make my application display the name property from the languages section in the response data, which looks like this:
[{
"name": "Colombia",
"topLevelDomain": [".co"],
"alpha2Code": "CO",
"alpha3Code": "COL",
"callingCodes": ["57"],
"capital": "Bogotá",
"altSpellings": ["CO", "Republic of Colombia", "República de Colombia"],
"region": "Americas",
"subregion": "South America",
"population": 48759958,
"latlng": [4.0, -72.0],
"demonym": "Colombian",
"area": 1141748.0,
"gini": 55.9,
"timezones": ["UTC-05:00"],
"borders": ["BRA", "ECU", "PAN", "PER", "VEN"],
"nativeName": "Colombia",
"numericCode": "170",
"currencies": [{
"code": "COP",
"name": "Colombian peso",
"symbol": "$"
}],
"languages": [{
"iso639_1": "es",
"iso639_2": "spa",
"name": "Spanish",
"nativeName": "Español"
}],
"translations": {
"de": "Kolumbien",
"es": "Colombia",
"fr": "Colombie",
"ja": "コロンビア",
"it": "Colombia",
"br": "Colômbia",
"pt": "Colômbia"
},
"flag": "https://restcountries.eu/data/col.svg",
"regionalBlocs": [{
"acronym": "PA",
"name": "Pacific Alliance",
"otherAcronyms": [],
"otherNames": ["Alianza del Pacífico"]
}, {
"acronym": "USAN",
"name": "Union of South American Nations",
"otherAcronyms": ["UNASUR", "UNASUL", "UZAN"],
"otherNames": ["Unión de Naciones Suramericanas", "União de Nações Sul-Americanas", "Unie van Zuid-Amerikaanse Naties", "South American Union"]
}],
"cioc": "COL"
}]
I have tried using pipes, nested *ngFor Loops but no luck in displaying the name of the language. Any suggestions?
In my template I am using the following HTML and interpolation to display the name of country object: How to use a similar approach to access the name property within the languages of the response data?
<div>
<label>Country Capital:</label>
<p>{{ country.capital }} </p>
</div>
My application consists of 3 Modules, 1 parent (CountryComponent) and two children components, (CountryListComponent) and (CountryDetailComponent). The data is sent from the List component to the Detail component using eventEmmiter. I am using the following model for the Country type:
export interface Country {
name: string;
topLevelDomain?: string[];
alpha2Code?: string;
alpha3Code?: string;
callingCodes?: string[];
capital?: string;
altSpellings?: string[];
region?: string;
subregion?: string;
population?: number;
latlng?: number[];
demonym?: string;
area?: number;
gini?: number;
timezones?: string[];
borders?: string[];
nativeName?: string;
numericCode?: string;
currencies?: Currency[];
languages?: Language[];
translations?: Translation;
flag?: string;
regionalBlocs?: Regional[];
cioc?: string;
}
In my List Component i use the following to fetch data using the service class and initialise the countries array of type Country, and use eventEmmiter to emit the country object to the Detail component:
public countries: Country[];
getCountries(){
this.countryService
.getCountries()
.subscribe((data: any) => {
this.countries = data;
},
error => {console.log('error loading')});
}
@Output() selectedCountry = new EventEmitter<Country>();
List Component Template:
<li class="list-group-item"
highlightDirective
style="cursor: pointer;
text-align: center;
font-family:'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;"
*ngFor="let country of countries | searchFilter: searchText : 'name'" (click)="onCountrySelected(country)">
{{ country.name }}
</li>
In Detail component i receive the event:
@Input() country: Country;
And in Detail Template i am trying to display it:
<h2> {{ country.name }} </h2>
<br>
<div class="row" #countrySelected>
<div class="col-sm">
<label>Country Capital:</label>
<p>{{ country.capital }} </p>
<p>{{ country.languages.name }}</p>
</div>
<div>
I use the eventEmmiter to send the country object from List component to the Detail component using the parent component, the parent template is as follows:
<div class="row"
style="padding-left: 20px;
padding-right: 20px;">
<div class="col-xs-5">
<app-country-list (selectedCountry)="childEventClicked($event)"></app-country-list>
</div>
<div class="col-xs-7">
<app-country-detail [country]="(selectedCountryEvent)"></app-country-detail>
</div>
</div>
Upvotes: 0
Views: 2520
Reputation: 31125
Given that each object is contained in an array, I assume that each property could contain more than one object as values. You could try the following.
I am assigning the respone from the API to a variable called countries
.
Controller
countries = [];
getData() {
this.apiService.getCountries().subscribe(
response => { this.countries = response; },
error => { // handle error }
);
}
Template
<div *ngFor="let country of countries">
<label>Country Capital:</label>
<p>{{ country.capital }} </p>
<label>Languages:</label>
<p *ngFor="let language of country.languages">{{ language.name }}</p>
<label>Currencies:</label>
<p *ngFor="let currency of country.currencies">{{ currency.name }}</p>
</div>
Update
There is an issue with the interface definition. The languages
property is defined as an array of type string
whereas it's a custom object. You could define a separate interface for each type of object. Try the following
export interface Country {
name: string;
topLevelDomain?: string[];
alpha2Code?: string;
languages?: Language[];
currencies?: Currency[];
translations?: Translate[];
regionalBlocs?: RegionalBloc[];
.
.
.
}
export interface Language {
iso639_1:? string;
iso639_2:? string;
name:? string;
nativeName:? string;
}
And the same goes for other properties currencies
, translations
and regionalBlocs
. Each need their own interface definitions similar to the one shown here for languages
.
Upvotes: 1