简体   繁体   中英

Correct way to display data from Rest Api in Angular

I have have a service in Angular, which calls data from an API. So when I am trying to display the data it is not displaying?

Service

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';

@Injectable()
export class ApiService {

   api: string = 'https://newsapi.org/v2/top-headlines?country=gb&category=entertainment&apiKey=8ee8c21b20d24b37856fc3ab1e22a1e5';

  constructor(
    private http: HttpClient,
  ) { }

getAll(): Observable<any> {
    return this.http.get(this.api)
    .pipe(
      catchError(this.handleError)
    );
  }

  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      console.log(error.error.message)

    } else {
      console.log(error.status)
    }
    return throwError(
      console.log('Something is wrong!'));
  };
}

Component.ts

import { Component, OnInit } from '@angular/core';
import { ApiService } from './api.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  public data = [];
  public noData: any;
  public results = [];

  constructor(
  private api: ApiService 
  ){ }

  getAll() {
    this.api.getAll().subscribe((results) =>  {
      this.data = results.results;
      console.log('JSON Response = ', JSON.stringify(results));
    })
  }

 ngOnInit() {

  }
}

JSON response structure

{ 
   "status":"ok",
   "totalResults":70,
   "articles":[ 
      { 
         "source":{ 
            "id":null,
            "name":"Thesun.co.uk"
         },
         "author":"Mary Gallagher",
         "title":"Holly Willoughby breaks down in tears on This Morning as she meets disabled boy who speaks against all odds - The Sun",
         "description":"",

etc etc

HTML

<div *ngFor="let news of data">
   <h3>{{news.json}}</h3>
</div>

Where Am I going wrong?

articles is a property of data, so you have to loop data.articles

Try like this:

<ng-container *ngFor = "let news  of data?.articles">
  <h3>{{news.title}}</h3>
</ng-container>

Another option:

TS:

this.data = results.articles;  // here now you have list of all articles

HTML:

*ngFor="let news of data"

Working Demo

When you ask for a "correct" way, it is commonly recommended to avoid subscriptions in component when you don't have to. Prefer async pipe instead.

import { Component, OnInit } from '@angular/core';
import { ApiService } from './api.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  public data$: Observable<Data[]>;

  constructor(
    private api: ApiService 
  ){ }

 ngOnInit() {
    this.data$ = this.api.getAll();
  }
}

<ng-container *ngIf="data$ | async as data; else pending">
  <div *ngFor="let article of data.articels">
     <h3>{{news.json}}</h3>
  </div>
</ng-container>

<ng-template #pending>
  <div>pending</div>
</ng-container>

Advantage: You never forget to unsubscribe, you have easy control over pending state

It looks like you are assigning object response, not array. So try to assign array:

this.data = results.results.articles;

OR add articles to iterate through array of articles:

<div *ngFor="let news of data?.articles">
   <h3>{{news.json}}</h3>
</div>

Please check once

<div *ngFor="let news of data.articles">
   <h3>{{news.author}}</h3>
</div>

With this JSON response:

{ 
   "status":"ok",
   "totalResults":70,
   "articles":[ 
      { 
         "source":{ 
            "id":null,
            "name":"Thesun.co.uk"
         },
         "author":"Mary Gallagher",
         "title":"Holly Willoughby breaks down in tears on This Morning as she meets disabled boy who speaks against all odds - The Sun",
         "description":"",

Your component should be:

import { Component, OnInit } from '@angular/core';
import { ApiService } from './api.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  public data = [];
  public noData: any;
  public results = [];

  constructor(
  private api: ApiService 
  ){ }

  getAll() {
    this.api.getAll().subscribe((results) =>  {
      this.data = results.articles;
    })
  }

 ngOnInit() {

  }
}

Your template:

<div *ngFor="let news of data">
   <h3>{{news.json}}</h3>
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM