I realize that the new updates don't require conversion of a response to JSON.
The tutorial I am following puts this into the api.service.ts
export class ApiService {
constructor(private http: HttpClient){}
messages = []
getMessage(){
this.http.get('http://localhost:3000/newroute').subscribe(res =>{
this.messages = res.json()
})
}
}
However, with the new update, "res.json()" does not work. I get the following error: Property 'json' does not exist on type 'Object'.
How can I solve this?
Here is the data I'm trying to loop through:
var posts = [
{message:'Hello World'},
{greeting:'Whats going on'}
]
Simply do:
getMessage(){
this.http.get('http://localhost:3000/newroute').subscribe(res =>{
this.messages = res;
})
}
Angular allows you to do type checking on the response. You don't have to manually parse JSON.
Here is a code snippet from your example (I recommend using types):
messages: Message[] = []
getMessage() {
this.http.get<Message[]>('http://localhost:3000/newroute').subscribe((res: Message[]) => {
this.messages = res;
});
}
(Update)
Based on your provided data, an interface for Message could look like this:
export interface Message {
[s: string]: string;
}
However, if "Messages" can only have specific keys like "message" and "greeting", then you can add any of those as optional properties as well.
export interface Message {
message?: string;
greeting?: string;
}
HttpClient gives you json object only, so no need to do .json() again.So do the following code it works for you
getMessage(){
this.http.get('http://localhost:3000/newroute').subscribe(res =>{
let messages: any = res;
this.messages = messages;
})
}
Related
I am not sure what I am doing wrong here.
I am trying to use the checkout facility for stripe using this documentation: https://stripe.com/docs/payments/checkout/accept-a-payment
I have configured my API to just return the checkoutid as a string.
The Angular service just calls the controller. When I run my code I actually get a nice 200 response and I can see the checkout id in the response body, but Angular throws an error:
SyntaxError: Unexpected token c in JSON at position 0 at JSON.parse () at XMLHttpRequest.onLoad (https://127.0.0.1:4200/vendor.js:18780:51) at ZoneDelegate.invokeTask
The service looks like this:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { map } from 'rxjs/operators';
import { environment } from '#environments/environment';
#Injectable({
providedIn: 'root',
})
export class StripeService {
private endpoint: string = 'stripe';
constructor(private http: HttpClient) {}
checkout(priceId: string) {
return this.http
.get<string>(`${environment.apiUrl}/${this.endpoint}/${priceId}`)
.pipe(
map((response) => {
console.log(response);
return response;
})
);
}
}
and I am invoking it like this:
this.stripeService
.checkout(this.button.priceId)
.subscribe((checkoutId: string) => {
console.log(checkoutId);
// this.stripe
// .redirectToCheckout({
// sessionId: checkoutId,
// })
// .then(function (result) {
// // If `redirectToCheckout` fails due to a browser or network
// // error, display the localized error message to your customer
// // using `result.error.message`.
// });
});
If I look in the network tab I can see this:
But the console actually shows this:
Does anyone have a scooby why?
Probably the response is a string and you haven't specified the response type. Try the following
this.http.get(
`${environment.apiUrl}/${this.endpoint}/${priceId}`,
{ responseType: 'text' }
)
Default response type is json.
It happened to me when my API return doesent match with my deserializable object on Angular. At first, try to check your returns entities
I'm having trouble with a .net core SPA app.
- Results are being passed back by the API call
- the SPA is not handling the results.
here is the pertinent code:
SPA ts:
class TestLibraryItem {
private _apiPath: string;
private _http: HttpClient;
public name: string;
public testResults: TestResult;
constructor(name: string, apiPath: string, http: HttpClient) {
this.name = name;
this._apiPath = apiPath;
this._http = http;
}
RunTests() {
this._http.get<TestResult>(this._apiPath)
.subscribe(result => {
this.testResults = result;
console.log(this.testResults);
console.log(this.testResults.CheckName);
});
}
}
class TestResult {
CheckName: string;
Checks: CheckResult[];
}
class CheckResult {
Test: string;
Pass: boolean;
}
and the console results when RunTests() is fired:
{"CheckName":"Check One","Checks":[{"Test":"Test one","Pass":true},{"Test":"Test two","Pass":true}]}
undefined
As far as I can tell, I'm getting valid json back from the API (indicated by console.log spitting it out, but it is not actually building the object which results in the undefined.
I think your properties in the JSON are parsed from upper case to lower case - CheckName -> checkName. As Javascript/Typescript is a case sensitive language you need to different property names.
Try to log with lower case and also change your property names to start with lower case. It is a common standard in Javascript/Typescript to start function and variable/property names via lower case.
console.log(this.testResults.checkName);
You are getting undefined because this console.log(this.testResults) is fired first
RunTests() {
this._http.get<TestResult>(this._apiPath)
.subscribe(result => {
this.testResults = result;
console.log(this.testResults);
console.log(this.testResults.CheckName === undefined ? '' : this.testResults['CheckName']);
});
}
or use SetTimeOut
RunTests() {
this._http.get<TestResult>(this._apiPath)
.subscribe(result => {
this.testResults = result;
console.log(this.testResults);
setTimeout(()=>{console.log(this.testResults['CheckName'])},2000);
});
}
I had a similar issue i.e. it looked lika valid json response but in fact it was a "text" response. Give the following a try:
getdData(inParams) {
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'application/json');
// need responseType = text (non object)
return this.http.get(environment.url, {
headers,
responseType: 'text'
});
}
hello i want to display the data that i got from a mongodb using a backend api (nodejs)
this is the code for event model
const mongoose = require('mongoose');
const config = require('../config/database');
// Events Schema
const EventSchema = mongoose.Schema({
eventname: {
type: String,
required: true
},
eventstartdate: {
type: String,
required: true
},
eventenddate: {
type: String,
required: true
},
eventcategorie: {
type: String
},
eventdescription: {
type: String
},
eventimage: {
type: String
}
});
const Event = module.exports = mongoose.model('Event', EventSchema);
this is the code from the router
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const config = require ('../config/database');
const User = require('../models/user');
const Event = require('../models/event');
//get event by id
router.get('/event/:eventid', (req,res) => {
Event.findById(req.params.eventid, (err, event) =>{
if (err){
return res.status(500).send({message:err.message});
}
if(!event){
return res.status(400).send({message:'Event not found'});
}
res.json({
event: {
id: event._id,
eventname: event.eventname,
eventstartdate: event.eventstartdate,
eventenddate: event.eventenddate,
eventcategorie: event.eventcategorie,
eventdescription: event.eventdescription,
eventimage: event.eventimage
}
});
});
});
and this is the code from the service in the angular
// GET an event by ID
displayEvent$(id: string) {
return this.http.get(`http://localhost:3000/users/event/${id}`)
.map(response => response.json());
}
then i created a simple method that is triggered by a button
and i passed an id of an event that i konw is in the database just to test it out
onclickeventpage(){
this.authService.displayEvent$('5ae0c8e96b40a71cd3b772cc').subscribe(event => {
console.log(event)
});
}
this gives me back at the console the event i need with every aribute
but whene i change this
console.log(event)
to this so i can get evey atribute separetly and then i an put them in the html
console.log(event.eventname)
i get undefined
i just want to know how to get every event atribute so i can display them in my html page
First you dont have to call .json() witn angular5
displayEvent$(id: string) {
return this.http.get(`http://localhost:3000/users/event/${id}`)
.map(response => response.json());
}
also you need to access
console.log(event.event.eventname);
HttpModule is deprecated and the new HttpClientModule by default formats the response to JSON so we no longer need to parse it using response.json():
I just want to know how to get every event attribute so that I can
display them on my HTML page
You can tell HttpClient the type of the response to make consuming the output easier and more obvious.
Typechecking of response can be done by using type parameter
export interface Ievent {
id:string
eventname: string
eventstartdate: string
eventenddate: string
eventcategorie: string
eventdescription: string
eventimage: string
}
Http returns an observable and We can tell the HttpClient.get to return response as Ievent type When we use http.get<Ievent>(...) then it returns the instance of Observable<Ievent> type.
In your service
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import {Ievent} from './eventModel'
#Injectable()
export class authService()
{
constructor(private http:HttpClient){}
displayEvent$(id: string)Observable<Ievent> {
return this.http.get<Ievent>(`http://localhost:3000/users/event/${id}`);
}
}
In your component subscribe to Observable<Ievent> to get instance of Ievent
onclickeventpage(){
this.authService.displayEvent$('5ae0c8e96b40a71cd3b772cc').subscribe(event => {
console.log(event);
console.log(event.eventname)});
}
I have a problem with my application in angular2. I need to connect to api to retrieve records to my Persons [] class. I want to use the second method to get people with individual id. I do the same way as in the tutorial on the Angular site but unfortunately I still have a fault
ERROR TypeError: Cannot read property 'Name' of undefined
This is my service
getPersons(): Promise<Person[]> {
var currentUser = JSON.parse(localStorage.getItem('currentUser'));
var token = currentUser.token;
let headers = new Headers({ 'Authorization': 'Bearer ' + token })
let options = new RequestOptions({ headers: headers });
return this.http.get(this.QuestionsUrl, options)
.toPromise()
.then(response => response.json() as Person[]);
}
getPerson(id: number): Promise<Person> {
return this.getPersons().then(persons => persons.find(person => person.Id === id));
}
My component:
export class PersonsComponent implements OnInit {
activePerson: any = {};
model: any = {};
constructor(private personService: PersonService, private route: ActivatedRoute, private location: Location) {
}
ngOnInit(): void {
this.route.paramMap.switchMap((params: ParamMap) => this.personService.getPerson(+params.get('Id')))
.subscribe(selected => this.activePerson = selected);
}
}
And html:
<body>
{{activePerson.Name}}
Try using
{{activePerson?.Name}}
With a question mark.
The issue is that the template attempts to display the value before the data is retrieved. At that point, activePerson is undefined. Hence the error message.
The "?" is called a safe navigation operator. It prevents navigating to the "dot" property (name in this example) unless the object to the left of the question mark has a value.
use
{{activePerson |json}}
to know if you are receiving any data
Consider this simple snippet of an AngularJS 2 application:
TestObject
export class TestObject {
id: number;
name: string;
}
TestService
[...]
export class TestService {
constructor(private http: Http) {}
test(): Observable<TestObject> {
return this.http
.get("http://www.example.com")
.map(this.save)
.catch(this.fail);
}
private save(response: Response) {
let testObject: TestObject = <TestObject> response.json();
return testObject || {};
}
private fail(error: any) {
return Observable.throw("error!");
}
}
AppComponent
[...]
export class AppComponent implements OnInit {
testObject: TestObject;
constructor(private testService: testService) {}
ngOnInit() {
this.testService.test().subscribe(
data => {
this.testObject = new TestObject();
console.log(this.testObject); // prints (empty) TestObject
this.testObject = data;
console.log(this.testObject); // prints object, not TestObject?
},
error => { }
);
}
}
Here my questions:
1) Why does my application print out (using Chrome Inspector) object and not TestObject as type?
2) The property testObject of class AppComponent should be of type TestObject. Why does my application not fail?
3) How can I achieve that I really get TestObject? What would be the best way to do it? Of course I could just manually fill up my TestObject, but I hoped there is some way of automatically mapping the json to my object.
Here is an answer that I wrote to a question which explained the handling of observables in angular2.
Angular 2 http post is returning 200 but no response is returned
Here you can see how I am handling the Response object as returned by the service. It is very important that you return your response object from the map function in service.
Similarly you can convert your response object to typescript type by casting your response object. The example can be:
this._loginService.login(this.username, this.password)
.subscribe(
(response) => {
//Here you can map the response to a type.
this.apiResult = <IUser>response.json();
//You cannot log your object here. Here you can only map.
},
(err) => {
//Here you can catch the error
},
() => {
//this is fired after the api requeest is completed.
//here you can log your object.
console.log(this.apiResult);
//result will only be shown here.
}
);
Here, it can be clearly seen that I am casting the response object to IUser type.
Another thing is while handling apiresponse in your component it is to be noted that the subscribe function has three arguments and if you will like to log your object, you must do it in the last function of subscribe.
Hope this helps!
your call must be like
ngOnInit() {
this.testService.test().subscribe(
(data) => {
this.testObject = new TestObject();
console.log(this.testObject); // prints (empty) TestObject
//only mapping
this.testObject = data;
},
error => { },
() => {
console.log(this.testObject);
}
);
}