Parsing json response from Http Request in Angular - json

I need to parse a json response containing two keys.
The response looks like
{
status: 0;
message: 'some error 404'
}
In pure nodejs or React you could just simply do: if (response.status===1)console.log('success').
However, I've been having a tough time doing this in angular. Could someone guide me and tell me how could I parse the JSON Response?
I have attached a mock-up of the code.
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Component } from '#angular/core';
#Component({
selector: 'app-create-employee',
templateUrl: './create-employee.component.html',
styleUrls: ['./create-employee.component.css']
})
export class CreateEmployeeComponent {
constructor(private http: HttpClient) { };
onFormSubmit() {
let options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
};
let body = new URLSearchParams();
body.set('data', 'stackoverflow');
this.http.post('http://localhost:8080/createEmployee', body.toString(), options)
.subscribe(response => {
console.log(response.status);
console.log(response.message);
});
}
}

According to the documentation, Angular can parse for you objects from string responses if you tell it how to do it. You can use this as an example.
First define an interface inside your component just below your imports:
export interface Response {
status: number,
message: string
}
This tells angular how to parse the json response from your server. The final bit is to use this interface in your post request like this:
this.http.post<Response>('http://localhost:8080/createEmployee', body.toString(), options)
.subscribe(response => {
console.log(response.status);
console.log(response.message);
});

Related

ANGULAR - Mapping nested JSON data from API

so I've been struggling for the past day or so with mapping the response from a mock API - I think I'm mapping it correctly but when I try to access the data it doesn't return anything in the HTML.
Please find my code below:
data.service.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { ConsentData, Prompt } from '#app/models/consent-data';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root',
})
export class ConsentWebviewDataService {
constructor(private httpClient: HttpClient) {}
getConsentData(): Observable<ConsentData<Prompt>> {
return this.httpClient.get<ConsentData<Prompt>>(
'MY_API_URL',
);
}
}
data.ts (interface)
export interface ConsentData<Prompt> {
prompts: Prompt[];
}
export interface Prompt {
promptId: number;
headline: string;
body: string;
imageUrl: string;
consents: string[];
type: string;
}
app.component.ts
export class PromptComponent implements OnInit {
consentData: any;
constructor(private consentWebviewDataService: ConsentWebviewDataService) {}
ngOnInit(): void {
this.consentWebviewDataService.getConsentData().subscribe(data => {
this.consentData = data.prompts.map(consents => {
return {
promptId: consents.promptId,
headline: consents.headline,
body: consents.body,
imageUrl: consents.imageUrl,
consents: consents.consents,
type: consents.type,
};
});
});
}
}
Lastly here is the API JSON response:
{"prompts":[{"promptId":100,"headline":"Headline","body":"Body text.","imageUrl":"https://picsum.photos/200","consents":["Consent 1","Consent 2","Consent 3"],"type":"ConsentCampaign"}]}
From what I understand so far, after countless tutorials and resources, the getCosentData() function sends request to API, then in the component I subscribe to it, get the response, assign the response to the consentData variable, then map the contents of the response based on the interface / how the JSON response looks.
However, the problem is that I cannot access the mapped data in the HTML. I don't need it in a table, just need to get the mapped data.
I tried all variations such as {{ consentData.promptId }} which I mapped, and it returns ERROR TypeError: ctx.consentData is undefined. Tried {{ consents.promptId }} as well, etc. but nothing works.
What am I missing here? And apologies for the long question && thanks in advance for any help!
You mapped the response into a new array and trying to access it as an object
Try {{ consentData[0].promptId }} to get the id of first element

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

http observable<any> - Angular 4

I need to display the data on html that I get from web service. I am able to see the data in a format that I want, but I can't display properly on html. I think -any- in http.get is the problem. I can read data in console without -any- but it works fine with . When it works with it, it still does not print in html properly. Can anyone provide advice on this?
html
<div>{{this.res}}</div>
app.component.ts
import { Component, OnInit } from '#angular/core';
//import { IMovie } from './movie';
import { AppService } from './app.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
res: any[] ;
errorMessage: string;
constructor(private _appService: AppService) { }
ngOnInit(): void { this.getData(); }
getData(): void {
this._appService.getData()
.subscribe(
(res: any []) => this.res = res,
(error: any) => this.errorMessage = <any>error);
}
}
app.service.ts :
Injectable()
export class AppService {
private urlNorth = '';
constructor(private http: HttpClient) { }
getData(): Observable<any> {
const headers = new HttpHeaders();
headers.set('Content-Type', 'text/sml');
headers.set('Accept', 'text/xml');
headers.set('Content-Type', 'text/xml');
return this.http.get<any>(this.urlNorth,{responseType:'text', headers: headers})
.do(data => {
// console.log(data)
var dataParsed = data.replace('<string xmlns="service">', '').replace('</string>', '').replace(/</g, '<').replace(/>/g, '>');
// console.log(dataParsed);
parseString(dataParsed, (err, res) => {
if (err) {
return console.dir('invalid XML');
}
else {
console.log(res);
console.log(res.NewDataSet.Table[0].DataPointName[0]);
}
})
})
.catch(this.handleError);
}
**data in console w/o any **
{{this.res}} in html
I'm pretty sure you don't have to put any at this line in app.service.ts
return this.http.get<any>(this.urlNorth,{responseType:'text', headers: headers})
because get method expects 0 type arguments.
Type any is not the problem. It's just TypeScript annotation to organise your code. The problem is you are refering to the res in inline template as this.res, but you should just res. However it won't work as you think. Looking at your data structure You will have to iterate throught this data due to Table is an array. Additionaly I Highly suggest to always represnt your data as class
export class Apps {
public Table: Array<any>; //here should be another type instead of "any"
/* rest of data if any */
}
Back to your question you should have in your html file <div>{{res}}</div> but that's just print your object as string if I good remember. So to properly access your data you should iterate through table using *ngFor
<div *ngFor="let el of res.NewDataSet.Table">
<span>{{el.BackColor}}</span>
<!-- all other data -->
</div>
It looks as though the data is coming back. I'll answer your initial question first (since you added a few issues in comments):
My guess is when you get data back, it's not showing because it's HTML, and angular doesn't like injecting html.
Add this to your TS:
import { DomSanitizer, SafeHtml } from '#angular/platform-browser';
res[]: safeHTML;
And change your html to this:
<div [innerHTML]="res"></div>
As mentioned in a previous answer, this is a solution for a single return of res, not an array of different htmls. If it's an array, you'll have to handle it accordingly. for instance:
<ng-container *ngFor="let r of res">
<div [innerHTML]="r">
</ng-container>

Angular doesn't pass HTTP GET params properly

So I figuring out my way around Angular. Just started with a OpenWeather API based application using a simple GET method.
So here is my 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;
constructor(private weather: WeatherService) { }
search() {
this.weather.getWeatherbyName(this.cityName);
}
}
As you can guess, the cityName variable is two way binded. The search() function is invoked onclick of a button and the data is passed to the weatherservice. The contents of weather service is:
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";
constructor(private Http: Http) { }
getWeatherbyName(name: string): Observable<any> {
let myParams = new URLSearchParams();
myParams.append('q', name);
myParams.append('appid', this.Appid);
// actual http request should look like this: http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=Chennai
return this.Http.get(this.APIurl, { search: myParams})
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
console.log(res.json());
let body = res.json();
return body.data;
}
private handleError(error: Response | any) {
console.error(error.message || error);
return Observable.throw(error.message || error);
}
}
But I get no error in my console or during the compile process. What is being done wrong? Also, how can I map the JSON I get to my class and give back that instance to the app.component?
Following is my class:
export class Weather {
city: String;
max_temp: String;
min_temp: String;
description: String;
}
And this is a sample JSON I receive:
{
"coord":{
"lon":80.28,
"lat":13.09
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04n"
}
],
"base":"stations",
"main":{
"temp":304.15,
"pressure":1008,
"humidity":79,
"temp_min":304.15,
"temp_max":304.15
},
"visibility":6000,
"wind":{
"speed":3.1,
"deg":160
},
"clouds":{
"all":75
},
"dt":1504629000,
"sys":{
"type":1,
"id":7834,
"message":0.0029,
"country":"IN",
"sunrise":1504571272,
"sunset":1504615599
},
"id":1264527,
"name":"Chennai",
"cod":200
}
As you can see all I need is some data from the JSON and not the whole thing.
Your main problem here is that you are not subscribing to the observable that is being produced by your getWeatherbyName function. Observables returned by Http are cold:
Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. (…) This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active.
In order to subscribe to this observable, you can simply update your search function to the following:
search() {
this.weather.getWeatherbyName(this.cityName)
.subscribe();
}
This is by no means the complete solution to your problem - You will want to do something in the subscription, such as assign the information received to properties of your component so that they can be rendered in the UI.
You appear to have other issues in your linked project, but I suggest you ask separate questions on Stack Overflow if needed, or even better, your favorite search engine should be able to help.
Try passing a RequestOptions object to the http get instead:
import { RequestOptions } from '#angular/http';
getWeatherbyName(name: string): Observable<any> {
let myParams = new URLSearchParams();
myParams.append('q', name);
myParams.append('appid', this.Appid);
let options = new RequestOptions({ search: myParams}); //<----- NEW
// actual http request should look like this: http://api.openweathermap.org/data/2.5/weather?appid=xxx&q=Chennai
return this.Http.get(this.APIurl, options) //<<----- NEW
.map(this.extractData)
.catch(this.handleError);
}

Angular 2 Form Serialization Into JSON Format

I am having a little bit of trouble creating my Angular 2 form and converting the submitted data into JSON format for the use of submitting it to my API. I am looking for something that works very similarly to this example:
$.fn.serializeObject = function()
http://jsfiddle.net/sxGtM/3/The only problem with this example is that the code is written in JQuery, whereas I'm trying to use strictly angular 2.
Any help would be greatly appreciated, I am still very new to angular.
You can use the getRawValue() function if you're using a FormGroup, to return an object that can then be serialized using JSON.stringify().
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder } from '#angular/forms';
import { Http } from '#angular/http';
#Component({
selector: 'my-component',
templateUrl: 'my-component.component.html'
})
export class MyComponent implements OnInit {
form: FormGroup;
constructor(private fbuilder: FormBuilder,
private http: Http) { }
ngOnInit(){
this.form = this.fbuilder.group({
name: '',
description: ''
});
}
sendToAPI(){
let formObj = this.form.getRawValue(); // {name: '', description: ''}
let serializedForm = JSON.stringify(formObj);
this.http.post("www.domain.com/api", serializedForm)
.subscribe(
data => console.log("success!", data),
error => console.error("couldn't post because", error)
);
}
}
You can use JSON.stringify(form.value):
submit() {
let resource = JSON.stringify(this.form.value);
console.log('Add Button clicked: ' + resource);
this.service.create(resource)
.subscribe(response => console.log(response));
}
Result in Chrome DevTools:
You are looking for JSON.stringify(object) which will give you the JSON represantation of your javascript object.
You can then POST this using the built-in HTTP service to your server.