I'm Trying to get key value pairs from json data via an external api and display it using angular and typescript. How can I achieve this?

痴心易碎 提交于 2021-02-11 14:12:29

问题


I would like to get each key value pair in the results object from my api to display on my front-end. ie(category, type, difficulty, questions correct_answer) I have the service and components set up correctly and all i need to do is fetch the json and display each pair. The method name is called fetchQuestions as seen below. I was able to successfully get data by just simply calling it the same way I did fetchPeople but the json format is not the same so it's not displaying. I then tried something else but that's not working either. How can I acheive displaying this?

People.service

 import { Injectable } from '@angular/core';
 import { Observable } from  'rxjs/Observable';
 import { HttpClient } from '@angular/common/http';
 import { map } from 'rxjs/operators';

 @Injectable({
 providedIn: 'root'
 })
 export class PeopleService {

 constructor(private http: HttpClient) { }


//this works like a charm as it is just a simple array

fetchPeople(): Observable <Object> {
return this.http.get('/assets/data/people.json')
}




// this doesn't work as the json from the api below is in a different 
  // json format. Plus I need to return all value pairs

fetchQuestions(): Observable <Object> {
return this.http.get('https://opentdb.com/api.php? 
 amount=10&difficulty=hard&type=boolean').map(res => 
res.json().results).subscribe(data => {
console.log(data););
    }
  }

API https://opentdb.com/api.php?amount=10&difficulty=hard&type=boolean

   {
   "response_code": 0,
   "results": [
   {
   "category": "Vehicles",
   "type": "boolean",
   "difficulty": "hard",
   "question": "In 1993 Swedish car manufacturer Saab experimented 
   with replacing the steering wheel with a joystick in a Saab 9000.",
   "correct_answer": "True",
   "incorrect_answers": [
    "False"
   ]
   },
   {
  "category": "History",
  "type": "boolean",
  "difficulty": "hard",
  "question": "Japan was part of the Allied Powers during World War 
  I.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
  },
  {
  "category": "History",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The Kingdom of Prussia briefly held land in Estonia.",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
  },
  {
  "category": "Science: Mathematics",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The binary number &quot;101001101&quot; is equivalent 
  to the Decimal number &quot;334&quot;",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
  },
  {
  "category": "Entertainment: Video Games",
  "type": "boolean",
  "difficulty": "hard",
  "question": "TF2: Sentry rocket damage falloff is calculated based 
 on the distance between the sentry and the enemy, not the engineer 
  and the enemy",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
 },
  {
  "category": "Entertainment: Video Games",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The names of Roxas&#039;s Keyblades in Kingdom Hearts 
  are &quot;Oathkeeper&quot; and &quot;Oblivion&quot;.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
},
{
  "category": "Entertainment: Music",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The band STRFKR was also briefly known as Pyramiddd.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
},
{
  "category": "Entertainment: Books",
  "type": "boolean",
  "difficulty": "hard",
  "question": "Harry Potter was born on July 31st, 1980.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
},
{
  "category": "Entertainment: Japanese Anime & Manga",
  "type": "boolean",
  "difficulty": "hard",
  "question": "Druid is a mage class in &quot;Log Horizon&quot;.",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
},
{
  "category": "Geography",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The two largest ethnic groups of Belgium are Flemish and Walloon. ",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
     ]
   }
 ]
}

People.page.ts

 import { Component, OnInit } from '@angular/core';
 import { PeopleService } from './../../providers/people.service'
 @Component({
 selector: 'app-people',
 templateUrl: './people.page.html',
 styleUrls: ['./people.page.scss'],
 })
 export class PeoplePage implements OnInit {

 people$;
 results$;
 constructor(private peopleService:PeopleService) { }

 fetchPeople(){
 this.people$ = this.peopleService.fetchPeople();
 }
 fetchQuestions(){
  this.results$ = this.peopleService.fetchQuestions()
 }




  ngOnInit() {
  }

 }

People.page.html

   <ion-toolbar>
   <ion-title>people</ion-title>
   </ion-toolbar>
   </ion-header>
   <ion-button (click) ="fetchPeople()"  color="primary">Primary</ion- 
   button>

   <ion-list>
   <ion-item *ngFor="let person of people$ | async">{{person.name}}. 
   </ion-item>
   </ion-list>
   <ion-button (click) ="fetchQuestions()"  
   color="primary">Secondary</ion-button>
   <ion-list>
            <ion-item *ngFor="let result of results$ | async">. 
             {{result.category}}</ion-item>
             <ion-item *ngFor="let result of results$ | async"> 
            {{result.questions}}</ion-item>
           <ion-item *ngFor="let result of results$ | async"> 
           {{result.difficulty}}</ion-item>
           <ion-item *ngFor="let result of results$ | async"> 
            {{result.correct_answer}}</ion-item>
   </ion-list>
  <ion-content>
 <ion-button color="primary">Primary</ion-button>
 </ion-content>

回答1:


The HTTP GET is a cold observable. As such each async will fire an individual request. Besides you aren't actually returning the observable from the fetchQuestions() function. The subscription should be removed.

You could also use Angular HttpParams to set the query parameters and do things the Angular way.

Try the following

Service

import { HttpClient, HttpParams } from '@angular/common/http';

fetchQuestions(): Observable<any> {
  const params = new HttpParams()
    .set('amount', '10')
    .set('difficulty', 'hard')
    .set('type', 'boolean');  
  return this.http.get('https://opentdb.com/api.php', { params: params })
    .pipe(map(res => res.results));
}

Template

<ng-container *ngFor="let result of results$ | async">
  <ion-list>
    <ion-item>{{result.category}}</ion-item>
    <ion-item>{{result.question}}</ion-item>
    <ion-item>{{result.difficulty}}</ion-item>
    <ion-item>{{result.correct_answer}}</ion-item>
  </ion-list>
</ng-container>

I also noticed a small type. result.questions should actually be result.question.

More details about hot vs cold observables: https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html

Working example: Stackblitz



来源:https://stackoverflow.com/questions/61510211/im-trying-to-get-key-value-pairs-from-json-data-via-an-external-api-and-display

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!