1

I have written a service for an API call to fetch the data. Below is my service code.

  export class SurveyServiceService {

  private surveysUrl = 
  'http://107.170.59.79/services/public/api/v1/countries';
  private headers = new Headers({'Content-Type': 'application/json'});

  constructor(private http: Http) { }

  getSurveys(): Promise<Survey[]> {
    return this.http.get(this.surveysUrl)
       .toPromise()
       .then(response => response.json() as Survey[])
       .catch(this.handleError);
  }
 }

Below is my component for getSurveys function

export class SurveysComponent implements OnInit {

  title = 'Survey List';
  surveys: Survey[];
  keys: String[];
  selectedSurvey: Survey;

  constructor(private router: Router,
    private surveyService: SurveyServiceService) { }

  ngOnInit(): void {
    this.getSurveys();
    this.keys = Object.keys(this.surveys);
  }

  getSurveys(): void {
    this.surveyService.getSurveys().then(surveys => this.surveys = surveys);
  }
 }

Since I am getting data in json object I tried to convert into array by using below code, so that I can iterate it using *ngFor in the HTML.

this.keys = Object.keys(this.surveys);

But when I run the code I receive an error as

TypeError: Cannot convert undefined or null to object

Can someone please let me know where I went wrong?

Bonzo
  • 427
  • 2
  • 10
  • 28
  • Http uses AJAX requests. The A means Asynchronous. The whole point of a promise is to represent the future result of an asynchronous operation. getSurveys() **sends** a request, then returns immediately. The surveys are only available later, when the callback function passed to then() has been executed. Put that `this.keys = Object.keys(this.surveys);` line **inside** the callback passed to then(). – JB Nizet Jun 03 '17 at 07:07
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Tamas Hegedus Jun 03 '17 at 07:55
  • Possible duplicate of [How do I return the response from an Observable/http/async call in angular2?](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2) – AT82 Jun 03 '17 at 09:16

2 Answers2

2

@JB Nizet's comment is right solution, I put answer here for clear code.

export class SurveysComponent implements OnInit {

  title = 'Survey List';
  surveys: Survey[];
  keys: String[];
  selectedSurvey: Survey;

  constructor(private router: Router,
    private surveyService: SurveyServiceService) { }

  ngOnInit(): void {
    this.getSurveys().then(surveys => {
       this.surveys = surveys;
       this.keys = Object.keys(this.surveys);
    });
  }

  getSurveys(){
    return this.surveyService.getSurveys();
  }
 }
Thien Hoang
  • 625
  • 3
  • 12
0

I tried to use a pipe but I had the same issue you faced. Instead, I use this as a workaround.

.subscribe(
    res =>
    {
    this.apiarray = []; <--- Empty array here
    console.log("response form api :  " + JSON.stringify(res));
    this.ResultfromApi= res;
    this.apiarray.push(this.PatientInfoFromApi);
    }

Now you just iterate over the array instead of the object. In the template, Your *ngFor loop goes like this

<tr *ngFor="let item of apiarray">
  <td>{{item.specific_key_to_your_result}}</td>
  ...
</tr>
Ahmed Hamed
  • 411
  • 4
  • 9