我正在尝试创建从端点返回的数据列表,我获取了10位数据,并且我想使用* ngFor来显示它们。我已经在正确的时间正确输入了数据,但这是说
错误错误:“无法找到类型为'object'的其他支持对象'[object Promise]'。NgFor仅支持绑定到数组等Iterable。”
不过,据我所见,您可以在Angular的最新版本的* ngFor中使用json。
JSON返回:https://pastebin.com/TTn0EqSS
app.component.html
<div [class.app-dark-theme]="true">
<mat-sidenav-container fullscreen class="sidenav-container">
<mat-toolbar class="toolbar">
Coin Market Cap 3rd party api app
</mat-toolbar>
<mat-card>
<mat-card-header>
<mat-card-title>CryptoCurrency Market Overview</mat-card-title>
<mat-card-subtitle>Top 15 current currencies.</mat-card-subtitle>
</mat-card-header>
<mat-card-content class="currency-listings">
<div *ngIf="finishedLoading">
<mat-grid-list cols="1" rowHeight="2:1">
<mat-grid-tile *ngFor="let currency of currenciesJson; let i = index" (click)="selectCurrency(i)">
{{currency.data[i].name}}
</mat-grid-tile>
</mat-grid-list>
test
test
test
</div>
</mat-card-content>
</mat-card>
<!-- (click)="showInfo(true)" -->
<mat-card *ngIf="displayInfo">
test
</mat-card>
</mat-sidenav-container>
</div>
coin-market-cap.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class CoinMarketCapService
{
key = "REDACTED";
apiUrl = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/';
constructor(public http: HttpClient) { }
getCurrencies(totalCurrencies: number)
{
let promise = new Promise((resolve, reject) => {
let url = this.apiUrl + "listings/latest?limit=" + totalCurrencies + "&CMC_PRO_API_KEY=" + this.key;
this.http.get(url)
.toPromise()
.then(
res => {
console.log(res);
resolve();
});
})
return promise;
}
getCurrency(currencyId: number)
{
console.log("in getcurrency");
let url = this.apiUrl + "info?id=" + currencyId + "&CMC_PRO_API_KEY=" + this.key;
console.log(url);
return this.http.get(url);
}
}
app.component.ts
import { Component } from '@angular/core';
import { CoinMarketCapService } from '../services/coin-market-cap.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent
{
currenciesJson = {};
displayInfo = false;
finishedLoading = false;
constructor(private CoinMarketCapService: CoinMarketCapService) {}
ngOnInit()
{
console.log(this.currenciesJson);
this.currenciesJson = this.CoinMarketCapService.getCurrencies(10)
.then(res =>
this.finishedLoading = true
)
console.log(this.currenciesJson);
console.log("exiting ngoninit");
}
selectCurrency(currencyId: number)
{
console.log(currencyId);
let currencyObject = this.CoinMarketCapService.getCurrency(currencyId);
}
showInfo ( showInfo: boolean )
{
this.displayInfo = showInfo;
}
}
答案 0 :(得分:3)
在Angular 6.1.something(最近发布)中,有一个用于迭代JSON对象的管道。
它称为KeyValuePipe-文档在这里-https://angular.io/api/common/KeyValuePipe
<div *ngFor="let item of object | keyvalue">
{{item.key}}:{{item.value}}
</div>
这是如此新,您必须使用最新版本的Angular6。如果您已经在Angular 6上运行,则只需运行:
ng update @angular/core
ng update @angular/cli
获取最新消息。
这是一篇文章-http://www.talkingdotnet.com/angular-6-1-introduces-new-keyvalue-pipe/
答案 1 :(得分:0)
ngFor遍历数组。但是,请阅读您的代码:
currenciesJson = {};
在这里将其初始化为对象。
this.currenciesJson = this.CoinMarketCapService.getCurrencies(10)
.then(res =>
this.finishedLoading = true
)
在这里,您将其初始化为一个承诺。
所以这可能行不通。它必须是一个数组。
我强烈建议您阅读the guide about HTTP,以了解如何正确使用HttpClient
来获取数据。您不应该使用promise,尤其是使用promise的方式,因为它并不是全部正确,并且充满了反模式。它应该归结为:
getCurrencies(totalCurrencies: number): Observable<Array<Currency>> {
const url = this.apiUrl + "listings/latest?limit=" + totalCurrencies + "&CMC_PRO_API_KEY=" + this.key;
return this.http.get<Array<Currency>>(url);
}
,然后在组件中:
currenciesJson: Array<Currency> = [];
...
this.CoinMarketCapService.getCurrencies(10).subscribe(currencies => this.currenciesJson = currencies);
请注意,指定类型如何使编译器告诉您代码中所有错误的地方。
答案 2 :(得分:0)
首先避免初始化:
将currenciesJson: object;
代替currenciesJson = {};
并将ngOnInit方法更改为:
ngOnInit()
{
this.CoinMarketCapService.getCurrencies(10)
.then(res => {
this.currenciesJson = res
this.finishedLoading = true
});
}
编辑
<mat-grid-tile *ngFor="let currency of currenciesJson.data; let i = index" (click)="selectCurrency(i)">
{{currency.name}}
</mat-grid-tile>
答案 3 :(得分:0)
解决此问题的最简单方法是创建TypeScript模型对象以将传入的json文件映射到。
例如,使用您自己的Json对象中的键:
export class CurrencyModel {
currency: string;
foo: number;
bar: number;
constructor(currency: string, foo: number, bar: number) {
this.currency = currency;
this.foo = foo;
this.bar = bar;
}
}
然后,您将使用以下方法创建对象模型的新实例:
currencyData: CurrencyModel;
getCurrency(currencyId: number)
{
console.log("in getcurrency");
let url = this.apiUrl + "info?id=" + currencyId + "&CMC_PRO_API_KEY=" + this.key;
console.log(url);
response = this.http.get(url);
response.subscribe(data => {
this.currencyData = data;
}, error1 => {
console.log(error1);
})
}
答案 4 :(得分:0)
* ngFor仅用于遍历数组,而不用于对象,您的响应包含具有status(对象)和data(对象数组)的对象。您可以像这样循环遍历对象数组。
this.currenciesJson = {
status : {},
data: [{}]
}
您只能循环使用CurrencyJson.data
尝试设置
<mat-grid-tile *ngFor="let currency of currenciesJson.data; let i = index" (click)="selectCurrency(currency)">
{{currency.name}}
</mat-grid-tile>
此外,如果使用angular 6.1,则可以通过keyValue pipr遍历对象键;如果使用angular 5,则可以使用Object.keys()遍历对象键,但是我认为您的问题是遍历“数据”而不是“键” >
答案 5 :(得分:0)
在这篇文章的评论/答案的帮助下,我达到了想要的目的。
此处使用了Angular 6.1s的新键值管道。 https://angular.io/api/common/KeyValuePipe
这很hacky,但是那很好。如果我要回到这个问题上,我肯定会改进很多,但确实有效。
这是这三个文件的来源。
app.component.ts
import { Component } from '@angular/core';
import { CoinMarketCapService } from '../services/coin-market-cap.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent
{
currenciesJson: object;
selectedCurrency: object;
displayInfo: boolean = false;
finishedLoading: boolean = false;
constructor(private CoinMarketCapService: CoinMarketCapService) {}
ngOnInit()
{
this.CoinMarketCapService.getCurrencies(15)
.then(res => {
this.currenciesJson = res,
this.finishedLoading = true;
});
}
selectCurrency(currencyId: number)
{
this.CoinMarketCapService.getCurrency(currencyId)
.then( res => {
this.selectedCurrency = res,
this.showInfo(true)
})
}
showInfo ( showInfo: boolean )
{
this.displayInfo = showInfo;
}
}
coin-market-cap.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class CoinMarketCapService
{
key: string = "REDACTED"; // https://pro.coinmarketcap.com/ free 6000 requests per month.
apiUrl: string = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/';
constructor(public http: HttpClient) { }
getCurrencies(totalCurrencies: number)
{
let promise = new Promise((resolve, reject) => {
let url: string = this.apiUrl + "listings/latest?sort=market_cap&cryptocurrency_type=coins&limit=" + totalCurrencies + "&CMC_PRO_API_KEY=" + this.key;
this.http.get(url)
.toPromise()
.then(
res => {
resolve(res);
});
})
return promise;
}
getCurrency(currencyId: number)
{
let promise = new Promise((resolve, reject) => {
let url: string = this.apiUrl + "info?id=" + currencyId + "&CMC_PRO_API_KEY=" + this.key;
this.http.get(url)
.toPromise()
.then(
res => {
resolve(res);
});
})
return promise;
}
}
app.component.html
<div [class.app-dark-theme]="true">
<mat-sidenav-container fullscreen class="sidenav-container">
<mat-toolbar class="toolbar">
Coin Market Cap 3rd party api app
</mat-toolbar>
<mat-card>
<mat-card-header>
<mat-card-title>CryptoCurrency Market Overview</mat-card-title>
<mat-card-subtitle>Top 15 current currencies.</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div *ngIf="finishedLoading">
<mat-grid-list cols="1" rowHeight="40px">
<mat-grid-tile *ngFor="let currency of currenciesJson.data | keyvalue; let i = index"
(click)="selectCurrency(currency.value.id)" class="grid-tile">
{{currency.value.name}}
</mat-grid-tile>
</mat-grid-list>
</div>
</mat-card-content>
</mat-card>
<mat-card *ngIf="displayInfo">
<mat-card-header>
<mat-card-title>Selected Cryptocurrency Details</mat-card-title>
<mat-card-subtitle>Name and links of selected currency</mat-card-subtitle>
</mat-card-header>
<mat-card-content *ngFor="let currency of selectedCurrency.data | keyvalue; let i = index">
Name: {{currency.value.name}} <br><br>
Ticker Symbol: {{currency.value.symbol}}<br><br>
Website: {{currency.value.urls.website}}<br><br>
Source Code: {{currency.value.urls.source_code}}<br><br>
Twitter: {{currency.value.urls.twitter}}
</mat-card-content>
</mat-card>
</mat-sidenav-container>
</div>