8

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?

4
  • Show console.log('JSON Response = ', results); output Commented Nov 29, 2019 at 11:32
  • Nothing in console. Commented Nov 29, 2019 at 11:32
  • JSON data structure added Commented Nov 29, 2019 at 11:34
  • @Sole I think you want that articles list? Commented Nov 29, 2019 at 11:38

6 Answers 6

10

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

Sign up to request clarification or add additional context in comments.

6 Comments

Maybe it is something to do with the JSON structure I am trying to get and it is not correct how I am calling?
Check the modified answer
@AdritaSharma I think it should results.articles?
@PrashantPimpale is correct, if you look at the real api response, it should be results.articles @AdritaSharma
Yesss... I see it now. Thanks @PrashantPimpale, c_ogoo
|
7

When you ask for a "correct" way, it is commonly recommended to avoid subscriptions in component when you don't have to. Prefer asyncpipe 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

Comments

3

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>

Comments

2

Please check once

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

Comments

0

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>

1 Comment

it does not work.
0

I am using Angular 20, @for is new syntax. With track expression determines a key used to associate array items with the views in the DOM

@for (news of data; track news.json) {
  <h3>{{news.json}}</h3>
} @empty {
  <h3>There are no json.</h3>
}

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.