如何使用* ngIf进行异步http.get数据请求 - Angular 2(How to use *ngIf for async http.get data request - Angular 2)

我有一个Web应用程序,它从多个api中检索数据,并且应该将数据用于某些图表。 问题是,当图表被渲染时,来自api的数据还没有。 我尝试使用.then()方法,但它告诉我property then does not exist on type void 。 此外,我尝试使用ngIf方法,遵循这个答案 ,但也没有工作。 你知道我怎么能解决这个问题?

下面是我的组件和我的组件模板。

app.component.ts

import { Component } from '@angular/core'; import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import 'rxjs/Rx'; import * as moment from 'moment'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Mimesi dashboard graphs'; //COUNTS public countIndexerMetaApi; //array of one number populated from http.get public countIndexerMetaNumber; //number extracted into array and stored as an int public countIndexerMetaArray; //array to store countNumber afterwards public countIndexerServedApi; public countIndexerServedNumber; public countIndexerServedArray; public countRealTimeServedApi; public countRealTimeServedNumber; public countRealTimeServedArray; //DATES public dateIndexerMetaToStore; //date got from moment method that needs to be stored public dateIndexerMetaArray; //array to store dates for graph label public dateIndexerServedToStore; public dateIndexerServedArray; public dateRealTimeServedToStore; public dateRealTimeServedArray; //API LINKS private apiCountIndexerMetaUrl: string = 'http://localhost:3000/api/countIndexerMetaApi'; /* TODO - API FOR COUNT OF OTHER TWO TABLES */ private apiCountIndexerServedUrl: string = 'http://localhost:3000/api/countIndexerServedApi'; private apiCountRealTimeServedUrl: string = 'http://localhost:3000/api/countRealTimeServedApi'; //VARIABLE FOR TIMEOUT public isDataAvailable:boolean = false; constructor(private http:Http) { let now = moment.locale("it"); //COUNT this.countIndexerMetaApi = 0; this.countIndexerMetaNumber = 0; this.countIndexerMetaArray = []; this.countIndexerServedApi = 0; this.countIndexerServedNumber = 0; this.countIndexerServedArray = [] this.countRealTimeServedApi = 0; this.countRealTimeServedNumber = 0; this.countRealTimeServedArray = [] //DATES this.dateIndexerMetaToStore = ""; this.dateIndexerMetaArray = []; this.dateIndexerServedToStore = ""; this.dateIndexerServedArray = []; this.dateRealTimeServedToStore = ""; this.dateRealTimeServedArray = []; } ngOnInit() { this.getIndexerMetaCount(); this.getIndexerServedCount(); this.getRealTimeServedCount(); } //COUNT getIndexerMetaCount(){ this.http.get(this.apiCountIndexerMetaUrl) .map((res: Response) => res.json()) .subscribe( data => { console.log(this.countIndexerMetaApi = data.map(countIndexerMetaApiObj => countIndexerMetaApiObj.countIndexerMetaApi)) }, ); //this.countIndexerMetaNumber = this.countIndexerMetaApi[0]; //<-- timing problem since this.count is not yet got from http.get() so it seems undefined //this.countIndexerMetaArray.push(this.countIndexerMetaNumber); // problem follows through } printCountIndexerMetaArray(){ this.countIndexerMetaApi.forEach(element => { console.log(element); }); } getIndexerServedCount(){ this.http.get(this.apiCountIndexerServedUrl) .map((res: Response) => res.json()) .subscribe( data => { console.log(this.countIndexerServedApi = data.map(countObj => countObj.countIndexerServedApi)) }, ); //this.countIndexerServedNumber = this.countIndexerServedApi[0]; //<-- timing problem since this.count is not yet got from http.get() so it seems undefined //this.countIndexerServedArray.push(this.countIndexerServedNumber); // problem follows through } printCountIndexerServedArray(){ this.countIndexerServedApi.forEach(element => { console.log(element); }); } getRealTimeServedCount(){ this.http.get(this.apiCountRealTimeServedUrl) .map((res: Response) => res.json()) .subscribe( data => { console.log(this.countRealTimeServedApi = data.map(countObj => countObj.countRealTimeServedApi)) }, ); //this.countRealTimeServedNumber = this.countRealTimeServedApi[0]; //<-- timing problem since this.count is not yet got from http.get() so it seems undefined //this.countRealTimeServedArray.push(this.countRealTimeServedNumber); // problem follows through } printRealTimeServedArray(){ this.countRealTimeServedApi.forEach(element => { console.log(element); }); } //DATES dateIndexerMeta() { this.dateIndexerMetaToStore = moment().add(-122, 'days'); this.dateIndexerMetaArray.push(this.dateIndexerMetaToStore); } dateIndexerServed() { this.dateIndexerServedToStore = moment().add(-122, 'days'); this.dateIndexerServedArray.push(this.dateIndexerServedToStore); } dateRealTimeServed() { this.dateRealTimeServedToStore = moment().add(-122, 'days'); this.dateRealTimeServedArray.push(this.dateRealTimeServedToStore); } //TIMEOUT TRIAL timeoutTrial(){ console.log(this.isDataAvailable); setTimeout(function() {this.isDataAvailable = true; console.log(this.isDataAvailable); }, 5000); //<-- timeout works but other functions don't refresh even if isDataAvailable changed } /* CHARTS */ //DATA public lineChartData:Array<any> = [ {data: this.countIndexerMetaArray, label: 'Indexer meta served links'}, ]; public lineChartData1:Array<any> = [ {data: this.countIndexerServedArray, label: 'Indexer served links'}, ]; public lineChartData2:Array<any> = [ {data: this.countRealTimeServedArray, label: 'Real-Time served links'}, ]; //LABELS public lineChartLabels:Array<any> = this.dateIndexerMetaArray; public lineChartLabels1:Array<any> = this.dateIndexerServedArray; public lineChartLabels2:Array<any> = this.dateRealTimeServedArray; //OPTIONS public lineChartOptions:any = { responsive: true, scales: { xAxes: [{ type: 'time', time: { displayFormats: { 'millisecond': 'DD MMM', 'second': 'DD MMM', 'minute': 'DD MMM', 'hour': 'DD MMM', 'day': 'DD MMM', 'week': 'DD MMM', 'month': 'DD MMM', 'quarter': 'DD MMM', 'year': 'DD MMM', } } }], }, }; public lineChartLegend:boolean = true; public lineChartType:string = 'line'; //COLORS public lineChartColors:Array<any> = [ { // grey backgroundColor: 'rgba(255,55,55,0.2)', borderColor: 'rgba(255,55,55,1)', pointBackgroundColor: 'rgba(255,55,55,1)', pointBorderColor: '#fff', pointHoverBackgroundColor: '#fff', pointHoverBorderColor: 'rgba(255,55,55,0.8)' }, ]; //EVENTS public chartClicked(e:any):void { console.log(e); } public chartHovered(e:any):void { console.log(e); } }

app.component.html

<div class="container"> <div class="front-end-app"> <ul> <h3>Count Indexer Meta:</h3> <li *ngFor="let countIndexerMetaNumber of countIndexerMetaApi"> {{countIndexerMetaNumber}} </li> <h3>Count Indexer Served:</h3> <li *ngFor="let countIndexerServedNumber of countIndexerServedApi"> {{countIndexerServedNumber}} </li> <h3>Count Real Time Served:</h3> <li *ngFor="let countRealTimeServedNumber of countRealTimeServedApi"> {{countRealTimeServedNumber}} </li> </ul> <hr> <div class="head"> <h1>{{title}}</h1> </div> <hr> <div class="row"> <div class="col-md-6"> <div class="card"> <div class="card-block"> <canvas baseChart width="600" height="400" [datasets]="lineChartData" [labels]="lineChartLabels" [options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" (chartHover)="chartHovered($event)" (chartClick)="chartClicked($event)"></canvas> </div> </div> </div> <div class="col-md-6"> <div class="card"> <div class="card-block"> <canvas baseChart width="600" height="400" [datasets]="lineChartData1" [labels]="lineChartLabels1" [options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" (chartHover)="chartHovered($event)" (chartClick)="chartClicked($event)"></canvas> </div> </div> </div> &t;div class="col-md-6 offset-md-3"> <div class="card"> <div class="card-block"> <canvas baseChart width="600" height="400" [datasets]="lineChartData2" [labels]="lineChartLabels2" [options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" (chartHover)="chartHovered($event)" (chartClick)="chartClicked($event)"></canvas> </div> </div> </div> </div> </div> <button type="button" class="btn btn-primary" (click)="printCountIndexerMetaArray()"> Click to print count indexer meta array</button> <button type="button" class="btn btn-primary" (click)="printCountIndexerServedArray()"> Click to print count indexer served array</button> <button type="button" class="btn btn-primary" (click)="printRealTimeServedArray()"> Click to print count real time served array</button> </div>

对于任何问题或进一步解释只是评论,我会马上回答。 谢谢!

I have a web application that is retrieving data from multiple api and is supposed to use the data into some charts. The problem is that when the charts get rendered the data from the api are not in yet. I tried using .then() method but it tells me that property then does not exist on type void. Furthermore I tried using the ngIf method, following this answer, but is not working either. Do you know how could I solve this please?

Below are my component and my component template.

app.component.ts

import { Component } from '@angular/core'; import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import 'rxjs/Rx'; import * as moment from 'moment'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Mimesi dashboard graphs'; //COUNTS public countIndexerMetaApi; //array of one number populated from http.get public countIndexerMetaNumber; //number extracted into array and stored as an int public countIndexerMetaArray; //array to store countNumber afterwards public countIndexerServedApi; public countIndexerServedNumber; public countIndexerServedArray; public countRealTimeServedApi; public countRealTimeServedNumber; public countRealTimeServedArray; //DATES public dateIndexerMetaToStore; //date got from moment method that needs to be stored public dateIndexerMetaArray; //array to store dates for graph label public dateIndexerServedToStore; public dateIndexerServedArray; public dateRealTimeServedToStore; public dateRealTimeServedArray; //API LINKS private apiCountIndexerMetaUrl: string = 'http://localhost:3000/api/countIndexerMetaApi'; /* TODO - API FOR COUNT OF OTHER TWO TABLES */ private apiCountIndexerServedUrl: string = 'http://localhost:3000/api/countIndexerServedApi'; private apiCountRealTimeServedUrl: string = 'http://localhost:3000/api/countRealTimeServedApi'; //VARIABLE FOR TIMEOUT public isDataAvailable:boolean = false; constructor(private http:Http) { let now = moment.locale("it"); //COUNT this.countIndexerMetaApi = 0; this.countIndexerMetaNumber = 0; this.countIndexerMetaArray = []; this.countIndexerServedApi = 0; this.countIndexerServedNumber = 0; this.countIndexerServedArray = [] this.countRealTimeServedApi = 0; this.countRealTimeServedNumber = 0; this.countRealTimeServedArray = [] //DATES this.dateIndexerMetaToStore = ""; this.dateIndexerMetaArray = []; this.dateIndexerServedToStore = ""; this.dateIndexerServedArray = []; this.dateRealTimeServedToStore = ""; this.dateRealTimeServedArray = []; } ngOnInit() { this.getIndexerMetaCount(); this.getIndexerServedCount(); this.getRealTimeServedCount(); } //COUNT getIndexerMetaCount(){ this.http.get(this.apiCountIndexerMetaUrl) .map((res: Response) => res.json()) .subscribe( data => { console.log(this.countIndexerMetaApi = data.map(countIndexerMetaApiObj => countIndexerMetaApiObj.countIndexerMetaApi)) }, ); //this.countIndexerMetaNumber = this.countIndexerMetaApi[0]; //<-- timing problem since this.count is not yet got from http.get() so it seems undefined //this.countIndexerMetaArray.push(this.countIndexerMetaNumber); // problem follows through } printCountIndexerMetaArray(){ this.countIndexerMetaApi.forEach(element => { console.log(element); }); } getIndexerServedCount(){ this.http.get(this.apiCountIndexerServedUrl) .map((res: Response) => res.json()) .subscribe( data => { console.log(this.countIndexerServedApi = data.map(countObj => countObj.countIndexerServedApi)) }, ); //this.countIndexerServedNumber = this.countIndexerServedApi[0]; //<-- timing problem since this.count is not yet got from http.get() so it seems undefined //this.countIndexerServedArray.push(this.countIndexerServedNumber); // problem follows through } printCountIndexerServedArray(){ this.countIndexerServedApi.forEach(element => { console.log(element); }); } getRealTimeServedCount(){ this.http.get(this.apiCountRealTimeServedUrl) .map((res: Response) => res.json()) .subscribe( data => { console.log(this.countRealTimeServedApi = data.map(countObj => countObj.countRealTimeServedApi)) }, ); //this.countRealTimeServedNumber = this.countRealTimeServedApi[0]; //<-- timing problem since this.count is not yet got from http.get() so it seems undefined //this.countRealTimeServedArray.push(this.countRealTimeServedNumber); // problem follows through } printRealTimeServedArray(){ this.countRealTimeServedApi.forEach(element => { console.log(element); }); } //DATES dateIndexerMeta() { this.dateIndexerMetaToStore = moment().add(-122, 'days'); this.dateIndexerMetaArray.push(this.dateIndexerMetaToStore); } dateIndexerServed() { this.dateIndexerServedToStore = moment().add(-122, 'days'); this.dateIndexerServedArray.push(this.dateIndexerServedToStore); } dateRealTimeServed() { this.dateRealTimeServedToStore = moment().add(-122, 'days'); this.dateRealTimeServedArray.push(this.dateRealTimeServedToStore); } //TIMEOUT TRIAL timeoutTrial(){ console.log(this.isDataAvailable); setTimeout(function() {this.isDataAvailable = true; console.log(this.isDataAvailable); }, 5000); //<-- timeout works but other functions don't refresh even if isDataAvailable changed } /* CHARTS */ //DATA public lineChartData:Array<any> = [ {data: this.countIndexerMetaArray, label: 'Indexer meta served links'}, ]; public lineChartData1:Array<any> = [ {data: this.countIndexerServedArray, label: 'Indexer served links'}, ]; public lineChartData2:Array<any> = [ {data: this.countRealTimeServedArray, label: 'Real-Time served links'}, ]; //LABELS public lineChartLabels:Array<any> = this.dateIndexerMetaArray; public lineChartLabels1:Array<any> = this.dateIndexerServedArray; public lineChartLabels2:Array<any> = this.dateRealTimeServedArray; //OPTIONS public lineChartOptions:any = { responsive: true, scales: { xAxes: [{ type: 'time', time: { displayFormats: { 'millisecond': 'DD MMM', 'second': 'DD MMM', 'minute': 'DD MMM', 'hour': 'DD MMM', 'day': 'DD MMM', 'week': 'DD MMM', 'month': 'DD MMM', 'quarter': 'DD MMM', 'year': 'DD MMM', } } }], }, }; public lineChartLegend:boolean = true; public lineChartType:string = 'line'; //COLORS public lineChartColors:Array<any> = [ { // grey backgroundColor: 'rgba(255,55,55,0.2)', borderColor: 'rgba(255,55,55,1)', pointBackgroundColor: 'rgba(255,55,55,1)', pointBorderColor: '#fff', pointHoverBackgroundColor: '#fff', pointHoverBorderColor: 'rgba(255,55,55,0.8)' }, ]; //EVENTS public chartClicked(e:any):void { console.log(e); } public chartHovered(e:any):void { console.log(e); } }

app.component.html

<div class="container"> <div class="front-end-app"> <ul> <h3>Count Indexer Meta:</h3> <li *ngFor="let countIndexerMetaNumber of countIndexerMetaApi"> {{countIndexerMetaNumber}} </li> <h3>Count Indexer Served:</h3> <li *ngFor="let countIndexerServedNumber of countIndexerServedApi"> {{countIndexerServedNumber}} </li> <h3>Count Real Time Served:</h3> <li *ngFor="let countRealTimeServedNumber of countRealTimeServedApi"> {{countRealTimeServedNumber}} </li> </ul> <hr> <div class="head"> <h1>{{title}}</h1> </div> <hr> <div class="row"> <div class="col-md-6"> <div class="card"> <div class="card-block"> <canvas baseChart width="600" height="400" [datasets]="lineChartData" [labels]="lineChartLabels" [options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" (chartHover)="chartHovered($event)" (chartClick)="chartClicked($event)"></canvas> </div> </div> </div> <div class="col-md-6"> <div class="card"> <div class="card-block"> <canvas baseChart width="600" height="400" [datasets]="lineChartData1" [labels]="lineChartLabels1" [options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" (chartHover)="chartHovered($event)" (chartClick)="chartClicked($event)"></canvas> </div> </div> </div> <div class="col-md-6 offset-md-3"> <div class="card"> <div class="card-block"> <canvas baseChart width="600" height="400" [datasets]="lineChartData2" [labels]="lineChartLabels2" [options]="lineChartOptions" [colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" (chartHover)="chartHovered($event)" (chartClick)="chartClicked($event)"></canvas> </div> </div> </div> </div> </div> <button type="button" class="btn btn-primary" (click)="printCountIndexerMetaArray()"> Click to print count indexer meta array</button> <button type="button" class="btn btn-primary" (click)="printCountIndexerServedArray()"> Click to print count indexer served array</button> <button type="button" class="btn btn-primary" (click)="printRealTimeServedArray()"> Click to print count real time served array</button> </div>

For any question or further explanation just comment and I'll answer straight away. Thanks!

最满意答案

只需使用布尔值来显示加载。

public isloading = true;

在http调用中,一旦获得所需的所有数据,将其设置为false。

this.http.get(this.apiCountRealTimeServedUrl) .map((res: Response) => res.json()) .subscribe( data => { this.countRealTimeServedApi = data.map(countObj => countObj.countRealTimeServedApi); this.isloading= false; }, );

在你的HTTP中有ngIf用于isloading部分

<div *ngIf="isloading" > loading .... </div> <div *ngIf="!isloading" > <!-- show the chart contents --> </div>

如果您有多个HTTP调用,请使用&&

<div *ngIf="isIndexMetaCountloading || isIndexerServedCountLoading || isRealTimeServedCountLoading" > loading ... </div> <div *ngIf="!isIndexMetaCountloading && !isIndexerServedCountLoading && isRealTimeServedCountLoading" > <!-- show the chart contents --> </div>

Just use a boolean to show loading.

public isloading = true;

Inside your http call , set this to false once you got all the data you want.

this.http.get(this.apiCountRealTimeServedUrl) .map((res: Response) => res.json()) .subscribe( data => { this.countRealTimeServedApi = data.map(countObj => countObj.countRealTimeServedApi); this.isloading= false; }, );

In your HTTP have ngIf for the isloading part

<div *ngIf="isloading" > loading .... </div> <div *ngIf="!isloading" > <!-- show the chart contents --> </div>

If you are having multiple HTTP calls then use &&

<div *ngIf="isIndexMetaCountloading || isIndexerServedCountLoading || isRealTimeServedCountLoading" > loading ... </div> <div *ngIf="!isIndexMetaCountloading && !isIndexerServedCountLoading && isRealTimeServedCountLoading" > <!-- show the chart contents --> </div>

更多推荐