Get titles from Wikipedia - json

I am kinda new to Angular.
I am trying to get 4 titles from Wikipedia API, but i can't figure up what's wrong in my code
this is the eample URL for 1 title
example URL = https://en.wikipedia.org/w/api.php?action=query&prop=pageprops&format=json&titles=Wilson_Lumpkin
model
IwikiItem.ts:
export interface IWikiItem {
batchcomplete?: string;
query?: Query;
}
export interface Query {
normalized?: Normalized[];
pages?: Pages;
}
export interface Normalized {
from?: string;
to?: string;
}
export interface Pages {
id?: The4101295;
}
export interface The4101295 {
pageid?: number;
ns?: number;
title?: string;
pageprops?: Pageprops;
}
export interface Pageprops {
defaultsort?: string;
page_image_free?: string;
wikibase_item?: string;
}
Component
private titles = [
'Wilson_Lumpkin',
'Robert Toombs',
'Saxby Chambliss',
'Wyche Fowler',
];
export class HomeComponent implements OnInit {
dataSource: MatTableDataSource<IWikiItem>;
constructor(private srv: SrvService) {
this.titles.forEach((name) => {
this.srv
.getWiki('action=query&prop=pageprops&format=json&titles=' + name)
.subscribe((data) => {
console.log(data.query),
(this.dataSource: new MatTableDataSource<IWikiItem[data]>);
(err) => {
console.log(err);
};
});
});
}
}
service
export class SrvService {
readonly base_url = 'https://en.wikipedia.org/w/api.php?';
getWiki(title: string) {
return this.http.get<IWikiItem>(this.base_url + title);
}
constructor(private http: HttpClient) {}
}
What's wrong here? i am, getting this error in console:
error msg
Edit 1
I am getting an error this.handle eror.
error

I guess Wikipedia APis does not support CORS. So instead of normal http request, you need t make a jsonp request.
For jsonp request you need to import module HttpClientJsonpModule in your application.
After that you can make the request like below.
Reference Link
getWiki(title: string) {
const url = this.base_url + title;
return this.http.jsonp(url, 'callback').pipe(
catchError(this.handleError) // then handle the error
);
}
callback(response) {
console.log("response", response);
}
handleError(error){
console.log(error);
}
Working sample Link

Related

How to get data of YAML file in the Angular 7 array of objects

I know how to get a JSON file and to show it in the array in Angular 7 but I am having a problem with the YAML file I have searched and I really do not know how to get in the array the YAML
For the moment I have tried this but it is coming with errors.
Service
#Injectable({
providedIn: 'root'
})
export class getYamlDataService {
constructor(private http: HttpClient) {
this.getJson().subscribe(data => {
console.log(data);
})
}
public getJson(): Observable<any> {
return this.http.get("./assets/swagger/swagger.yaml");
}
}
Component.ts
constructor(private getYamlData: getYamlDataService) {}
ngOnInit() {
this.getYamlData.getJson().subscribe(data => {
console.log(data);
});
Error
Http failure during parsing for http://localhost:4200/assets/swagger/swagger.yaml
But when I open this localhost then it is showing in browser yaml file.
This is due to your response being parsed as a JSON Object instead of returning a plain string. If you look at the API of HttpClient.get(string) without an options parameter, you will see that the response is observed as a json (found here, 15th overload)
get<T>(url: string, options?: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }): Observable<T>
You have to specify the return type you want (in this case most likely "text")
#Injectable({
providedIn: 'root'
})
export class getYamlDataService {
constructor(private http: HttpClient) {
this.getJson().subscribe(data => {
console.log(data);
})
}
public getJson(): Observable<any> {
return this.http.get("./assets/swagger/swagger.yaml", {
observe: 'body',
responseType: "text"; // This one here tells HttpClient to parse it as text, not as JSON
});
}
}
If you want to use that yaml as a JavaScript Object, you will have to parse it yourself. Luckily, there are already libararies like yaml.js that you can leverage for this. First, install the libarary npm i --save yamljs and then use it like this:
import {parse} from 'yamljs';
import {map} from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class getYamlDataService {
constructor(private http: HttpClient) {
this.getJson().subscribe(data => {
console.log(data);
})
}
public getJson(): Observable<any> {
return this.http.get("./assets/swagger/swagger.yaml", {
observe: 'body',
responseType: "text" // This one here tells HttpClient to parse it as text, not as JSON
}).pipe(
// Map Yaml to JavaScript Object
map(yamlString => parse(yamlString))
);
}
}
Here is a working StackBlitz showcasing this.
Edit: Added example for parsing the returned string to a JavaScript Object
Edit2: Added StackBlitz example

Angular HTTP GET

I have a server running on "localhost:3000". It displays data as JSON at e.g. "localhost:300/locations".
My "data.service.ts" includes this code:
path: string = 'http://localhost:3000'
constructor(private http: HttpClient) { }
// Locations
getAllLocations(): Observable<Location[]> {
let location = null;
this.http.get(this.path + '/locations')
.map((res => location = res))
.catch((error: any) => Observable.throw(console.log(error)));
return location;
}
In my result.component.ts I'm running this code:
constuctor(private dataservice: DataService) { }
ngOnInit() {
console.info(this.dataservice.getAllLocations());
}
I'm expecting to get as output all Locations as JSON, instead of this the output is "null".
Does anyone have a suggestion on how to make this work properly?
UPDATE:
Also tried this for the HTTP call:
getAllLocations(): Observable<Location[]> {
this.http.get<Location[]>(this.path + '/locations')
.pipe(
tap(items => console.info('fetched items'))
);
}
The output for this code is unfortunately: "Object { _isScalar: false, source: {...}, operator: {...} }"
Did you know that HttpClient#get returns an Observable? You can just return the get method in your method.
Secondly, you can set an interface to the method so that it'll return the JSON as typed.
Lastly, you can use template literals in your API URL.
/**
* Retrieves a list of locations.
* (TODO: Add better documentation here)
*/
getAllLocations(): Observable<Location[]> {
return this.http.get<Location[]>(`${this.path}/locations`);
}
You can then handle this in the actual component that calls this method:
constuctor(private dataservice: DataService) { }
ngOnInit() {
this.dataservice.getAllLocations().subscribe(result => {
console.log(result);
});
}
You have to return Observable from the service:
path: string = 'http://localhost:3000'
constructor(private http: HttpClient) { }
// Locations
getAllLocations(): Observable<Locations[]> {
return this.http.get(this.path + '/locations').pipe(
map((res => location = res)),
catch((error: any) => Observable.throw(console.log(error))));
}
And subscribe to it in the component.
constructor(private dataservice: DataService) { }
ngOnInit() {
this.dataservice.getAllLocations().subscribe(result => {
console.log(result);
})
}

Angular http request with interface: statusText: "Unknown Error"

I am trying to call an example API (https://jsonplaceholder.typicode.com/posts) in Angular via the use of an interface.
However I am getting the following error. ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}
My code for my TS file is below
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { HttpClient } from '#angular/common/http';
interface Post {
title: string;
body: string;
};
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController, private http: HttpClient) {
}
ionViewDidLoad() {
this.getData();
}
getData() {
this.http.get<Post>('https://jsonplaceholder.typicode.com/posts').subscribe(res => {
let postTitle = res.title;
console.log(postTitle);
});
}
}
well, your code has a few problems for one res is of Array type and if you want to access your objects property you'll have to loop through it (perhaps something like this:)
let postTitle = [];
this.http.get<Post>('https://jsonplaceholder.typicode.com/posts').subscribe(res => {
res.forEach(element => {
postTitle.push(element);
});
console.log(postTitle);
});
and I strongly recommend to call an API via a service don't do it in a component.
So I tried to replicate this with
https://stackblitz.com/edit/angular-njzmwr
I found an issue that, your current api is returning data as an array so either selects the data by the filter from array or something else.
pls check the above-mentioned URL
The API returns and Array of PostS. Try:
getData() {
this.http.get<Post[]>('https://jsonplaceholder.typicode.com/posts').subscribe(res => {
let postTitle = res[0].title;
console.log(postTitle);
});
}
HTH

Retrieve html from server and display with Angular

I'm trying to retrieve HTML from a REST service and display it using Angular (4.3). I can watch the service get called and return the correct content. However, the angular component using this never seems to actually receive the content. What have I missed?
Specifically a console.log(html) (in the second code sample below) always outputs null.
I have an angular service that looks like:
#Injectable()
export class SlidesService {
private requestUrl: string;
constructor(
#Inject(AppConfig) private config: AppConfig,
#Inject(HttpClient) private http: HttpClient) {
this.requestUrl = this.config.restRoot + listSlidesUrl;
}
getSlide(deck: string, slide: string): Observable<string> {
const headers: HttpHeaders = new HttpHeaders({'Accept': 'text/html'});
const thisUrl: string = this.requestUrl + '/' + deck + '/' + slide;
return this.http.get<string>(thisUrl, { headers: headers });
}
}
This is used by a component:
export class SlidePreviewComponent implements OnInit {
#Input() slide: string; /* Identifier for the slide */
#Input() deck: string;
slideHtml: string;
constructor(private slideService: SlidesService) {
}
ngOnInit(): void {
this.slideService.getSlide(this.deck, this.slide)
.subscribe(html => this.setSlideHtml(html) );
}
setSlideHtml(html: string) {
this.slideHtml = html;
console.log(html);
}
}
The new HttpClient class expects the get() method to return JSON response. If you expect a text (HTML), it's necessary to specify it in the request options:
this.http.get(thisUrl, { headers: headers, responseType: 'text' });
The special Accept header may be unnecessary then.
Hi can you try this in service
getSlide(deck: string, slide: string){
const thisUrl: string = this.requestUrl + '/' + deck + '/' + slide;
return this.http
.get(url ,{ headers: headers, responseType: 'text' })
.toPromise()
.then(resp => resp.text())
.catch(error=>console.log(error))
}
and your component
ngOnInit(): void {
this.slideService.getSlide(this.deck, this.slide)
.subscribe(html => this.setSlideHtml(html) );
}
setSlideHtml(html) {
this.slideHtml = html;
console.log(html);
}
in your template
<div id="scroll" [innerHTML]="slideHtml"></div>

Angular 4 map certain JSON data to class and return observable

So I am trying to learn some basic Angular by creating an application that fetches and displays the current weather of a location using OpenWeather API.
This is what I have in my code currently:
app.component.ts:
import { Component } from '#angular/core';
import { WeatherService } from './weather.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [WeatherService]
})
export class AppComponent {
title = 'Ng-Weather';
cityName: string;
weather: Weather;
constructor(private weather: WeatherService) { }
search() {
this.weather.getWeatherbyName(this.cityName)
.subscribe(res => this.weather = res);
console.log(this.weather);
}
}
weather.service.ts:
import { Injectable } from '#angular/core';
import { Http, Response, URLSearchParams } from '#angular/http';
import { Observable } from 'rxjs';
import { Weather } from './weather';
#Injectable()
export class WeatherService {
APIurl = "http://api.openweathermap.org/data/2.5/weather";
Appid = "xxx";
weather: Weather;
constructor(private http: Http) { }
getWeatherbyName(name: string): Observable<any> {
let myParams = new URLSearchParams();
myParams.append('appid', this.Appid);
myParams.append('q', name);
return this.http.get(this.APIurl , { search: myParams} )
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
this.weather.city = body.name;
this.weather.description = body.weather[0].main;
this.weather.temp = body.main.temp;
console.log(this.weather);
}
private handleError(error: Response | any) {
console.error(error.message || error);
return Observable.throw(error.message || error);
}
}
weather.ts:
export class Weather {
city: String;
description: String;
temp: String;
}
So basically I am trying to map a JSON returned from OpenWeather API and get only some parts of the data and not the whole thing. The JSON returned is like following:
{
"coord":{
"lon":80.28,
"lat":13.09
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03n"
}
],
"base":"stations",
"main":{
"temp":303.15,
"pressure":1008,
"humidity":79,
"temp_min":303.15,
"temp_max":303.15
},
"visibility":6000,
"wind":{
"speed":3.1,
"deg":210
},
"clouds":{
"all":40
},
"dt":1504805400,
"sys":{
"type":1,
"id":7834,
"message":0.0017,
"country":"IN",
"sunrise":1504744074,
"sunset":1504788314
},
"id":1264527,
"name":"Chennai",
"cod":200
}
When the above code is executed, I get this error:
weather.service.ts:32 Cannot set property 'city' of undefined
Also how do I return an observable of type Weather and return that variable weather and catch it on the app.component.ts?
You are not creating an instance of the weather object before assigning its properties. You can do that explicitly like this:
this.weather = new Weather();
this.weather.city = body.name;
this.weather.description = body.weather[0].main;
this.weather.temp = body.main.temp;
console.log(this.weather);
OR
You can do something like this:
this.weather = {
city: body.name,
description: body.weather[0].main,
temp: body.main.temp
}
console.log(this.weather);
And to answer the second part of your question, you should be able to do this:
getWeatherbyName(name: string): Observable<Weather> {
// your other code
}
private extractData(res: Response) {
// your other code
return this.weather;
}
And to answer the third part of your question ... Observables are asynchronous. This means that they do not immediately return a value. Rather they provide for definition of a callback function that is executed when the data is returned. That means that the data is undefined until the data is returned and the callback function is executed.
So if you want to access the returned data in your code, you need to do in WITHIN the callback function. Like this:
search() {
this.weather.getWeatherbyName(this.cityName)
.subscribe(res => {
this.weather = res;
console.log(this.weather);
});
}