0

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!

4
  • 1
    There's too much code. Have you tried *ngIf="items | async as mydata" and inside *ngFor="item of mydata"? Where items in a Promise which should resolve an iterable. Commented Jul 7, 2017 at 8:39
  • sorry, the part that doesn/t work is the lineChartData variable, the three loops on top work fine Commented Jul 7, 2017 at 8:48
  • 1
    Anyway, try as he said : *ngIf="items | async" and *ngIf="items | async as mydata" Commented Jul 7, 2017 at 8:56
  • Sorry but I'm pretty new with angular, I tried implementing it but it doesn't work or maybe I'm doing it wrong. Do you know how should I implement it please? Commented Jul 7, 2017 at 9:22

3 Answers 3

1

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>
Sign up to request clarification or add additional context in comments.

Comments

0

U forget implements OnInit [https://angular.io/guide/lifecycle-hooks][1]

export class AppComponent implements OnInit{

Try use Resolver for this component [https://angular.io/api/router/Resolve][2]

1 Comment

Thanks for the answer. The problem is that I don't have any interface in order to use resolve. I tried using DoCheck() and it doesn't work. Any other idea?
0

I am not getting what exactly is your problem, could you please clarify a little more. But if your problem is with these lines

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

then it's not working because get method works asynchronously, and therefore this.countIndexerServedApi is yet not initialized. So, to overcome this problem you should move these statements inside the subscribe block and then these statements will be executed only after this.countIndexerServedApi gets initialized.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.