I learn Angular2 and now i try to get my data from a rest service. My rest service works and i can get data from there.
But angular always give my this error message: JSON.parse: unexpected character at line 1 column 1 of the JSON data
This is my Service:
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Person } from '../_models/person';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class PersonService {
private headers: Headers;
constructor(private http: Http)
{
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.headers.append('Accept', 'application/json');
}
getPersons(): Observable<Person[]> {
return this.http.get('http://localhost:54612/api/Person')
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
private handleError(error: Response | any) {
// In a real world app, we might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
This is the component for the view:
import { Component, OnInit } from '#angular/core';
import { Person } from '../_models/person';
import { PersonService } from '../_services/person.service';
#Component({
moduleId: module.id,
templateUrl: 'login.component.html',
providers: [ PersonService ]
})
export class LoginComponent implements OnInit {
errorMessage: string;
personen: Person[] = [];
constructor(private personService: PersonService) { }
ngOnInit() { this.getPersons(); }
getPersons() {
this.personService.getPersons()
.subscribe(
personen => this.personen = personen,
error => this.errorMessage = <any>error);
}
}
And this is my view:
<h1>Tour of Heroes</h1>
<h3>Heroes:</h3>
<ul>
<li *ngFor="let person of personen">{{person.IDPerson}}</li>
</ul>
<p class="error" *ngIf="errorMessage">{{errorMessage}}</p>
Your server is return XML. The reason is probably because it's the default when you don't explicitly set the Accept to something else. You have set it in the Headers to JSON, but you never add the headers to the request. You need to do
this.http.get('http://localhost:54612/api/Person', { headers: this.headers });
Try this snippet, in your getPersons()
return this.http.get('http://localhost:54612/api/Person',{headers: this.headers })
.map((response:Response) => response.json())
Related
im tryng to get the response from this http.get
getChatId(emailTo): any {
var email = emailTo
const httpOptions = {
headers: new HttpHeaders({
'Accept': 'application/json',
'Content-Type': 'application/json',
'Token': this.token_value
})
};
this.httpClient.get("https://xxxx=" + email, httpOptions)
.subscribe(data => {
console.log(data['_body']);
return data
}, error => {
console.log(error);
return error
});
}
this inside my constructor
this.getChatId(this.emailTo).then((date) => {
var docRef = firebase.firestore().collection("xxx").doc(date.response);
docRef.onSnapshot((doc) => {
this.document = doc.data()
let chats_message = [];
for (let k in this.document.messages) {
chats_message.push(this.document.messages[k]);
}
chats_message.sort(function (a, b) { return a.id - b.id; })
this.messages_chat = chats_message;
this.content.scrollToBottom(300);//300ms animation speed
console.log("Array", this.messages_chat);
})
});
but it give me this error:
vendor.js:1823 ERROR Error: Uncaught (in promise): TypeError: Cannot
read property 'subscribe' of undefined TypeError: Cannot read property
'subscribe' of undefined
Subscribe is not a function in httpclient while the request. please follow the below code
import { Component } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '#angular/common/http';
#IonicPage()
#Component({
selector: 'page-sample',
templateUrl: 'sample.html',
})
export class SamplePage {
sampleDatas: Observable<any>;
constructor(public navCtrl: NavController, public httpClient: HttpClient) {
this.films = this.httpClient.get('https://swapi.co/api/films');
this.sampleDatas
.subscribe(data => {
console.log('my data: ', data);
})
}
You should rewrite your function as an Observable to interact with the httpclient. Preferably in a service file like ChatService. You can design the http request with models or any types you receive or send.
export class ChatService {
constructor(private http: HttpClient) {}
getChatId(emailTo: string): Observable<any> {
return this.httpClient.get<any>("https://xxxx=/" + email);
}
}
Call the http request on a page with the service injected in the constructor.
constructor(private chatService: ChatService) {}
getChatId() {
this.chatService.getChatId(this.emailTo).subscribe(
result => {
// do something with result
},
error => {
// do something with error
}
);
}
EDIT
If you work with models to pass and receive data in the http request, you can define them as type. https://blog.angular-university.io/angular-http/
import { User } from '../models/user';
export class ChatService {
constructor(private http: HttpClient) {}
getChatId(emailTo: string): Observable<User> {
return this.httpClient.get<User>("https://xxxx=/" + email);
}
}
i am consuming Rest JSONP Web Service in an ionic App which works fine on PC but returns null value on mobile devices
My page.ts file
import {
Component,
OnInit
} from '#angular/core';
import {
AlertController,
LoadingController
} from '#ionic/angular';
import {
ActionSheetController
} from '#ionic/angular';
import {
Router
} from '#angular/router'
import {
ProApiService
} from './../../../../services/pro-api.service';
#Component({
selector: 'app-ranked-diagnosis',
templateUrl: './ranked-diagnosis.page.html',
styleUrls: ['./ranked-diagnosis.page.scss'],
})
export class RankedDiagnosisPage implements OnInit {
tabSelect: string = 'show10';
show10Data: Array < any >= [];
showAllData: Array < any >= [];
redFlagsData: Array < any >= [];
loading: any;
constructor(
private api: ProApiService,
public alertController: AlertController,
public loadingController: LoadingController,
public actionSheetController: ActionSheetController,
private router: Router
) {}
segmentChanged(event: any) {
this.tabSelect = event.detail.value;
}
async presentActionSheet(buttons) {
const actionSheet = await this.actionSheetController.create({
header: 'Sub Diagnosis',
buttons: buttons
});
await actionSheet.present();
}
async presentAlert(msg: string, header: string) {
const alert = await this.alertController.create({
header: '',
subHeader: header,
message: msg,
buttons: ['OK']
});
await alert.present();
}
async presentLoading() {
this.loading = await this.loadingController.create({
message: 'loading...',
});
return await this.loading.present();
}
ngOnInit() {
}
ionViewWillEnter() {
if (this.api.ProApiData.diagnoses_checklist.diagnoses) {
this.showAllData =
this.api.ProApiData.diagnoses_checklist.diagnoses;
for (let i = 0; i < 10; i++) {
this.show10Data.push(this.showAllData[i]);
}
this.showAllData.forEach(item => {
if (item.red_flag == 'true') {
this.redFlagsData.push(item);
}
});
console.log(this.showAllData);
} else {
console.log('error');
this.router.navigateByUrl('isabel-pro');
}
}
why_diagnosis(url: any, weightage: any) {
this.presentLoading();
this.api.why_diagnosisApi(url).subscribe(res => {
let matched_terms = res._body.why_diagnosis.matched_terms;
console.log(matched_terms);
let alertMsg = `We matched the terms: ${matched_terms}<br><hr>Degree of match between query entered and database: ${weightage}`;
this.presentAlert(alertMsg, 'Why did this diagnosis come up ?');
this.loadingController.dismiss();
}, err => {
this.loadingController.dismiss();
console.log('error');
});
}
}
in the above code i am calling why_diagnosis function which calls the function from a service file.
My service.ts file
import {
Injectable
} from '#angular/core';
import {
HttpClient,
HttpHeaders
} from '#angular/common/http';
import {
Jsonp
} from '#angular/http';
import {
Observable
} from 'rxjs';
import {
map
} from 'rxjs/operators';
import {
ConstantsService
} from './../../../services/constants.service';
#Injectable({
providedIn: 'root'
})
export class ProApiService {
apiRoot = this.root.APIroot;
diagnosisPROData: any;
drugData: any;
ProApiData: any;
drugApiData: any;
constructor(
private jsonp: Jsonp,
private http: HttpClient,
private root: ConstantsService) {}
why_diagnosisApi(url: any): Observable < any > {
let whyUrl = `${this.apiRoot}Mob_isabelPRO.php?
why_url=${url}&callback=JSONP_CALLBACK`;
return this.jsonp.request(whyUrl, 'callback')
.pipe(
map(
res => {
let why_diagnosis = res;
return why_diagnosis;
}
)
);
}
}
above code is from my service file.
this is the value i am getting in PC
this is the return on mobile
i dont know whats wrong with it. please suggest me the solution
Thanks
I have build an interceptor for making HTTP requests to a PHP backend.
This backend gives an JWT token to the app and I save this in the Ionic Storage.
But I want to get that token from Storage and add it as an header to the HTTP request.
Below is my interceptor with and hardcoded token.
This works and I get a response from the backend.
See update # bottom of this post
http-interceptor.ts
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', 'Bearer MY TOKEN')});
return next.handle(changedReq);
}
}
But how do I get the token from storage into the header.
I searched alot and most of the tutorials / examples are from the older HTTP module. If someone has an idea or has a up2date example ?
UPDATE
Oke below code send the token
intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
return fromPromise(this.Auth.getToken())
.switchMap(token => {
const changedReq = req.clone({headers: req.headers.set('Authorization', 'Bearer ' + token )});
return next.handle(changedReq);
});
}
With 1 exception, namely the first time I access that page :)
You can save JWT token in, for example, localStorage
localStorage.setItem('myToken', res.token);
and then access it with
localStorage.getItem('myToken');
In your case something like this:
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', localStorage.getItem('myToken'))});
return next.handle(changedReq);
}
}
If you want to use Ionic Storage
import { HttpInterceptor, HttpRequest } from '#angular/common/http/';
import {HttpEvent, HttpHandler} from '#angular/common/http';
import { AuthProvider } from "../providers/auth/auth";
import {Injectable} from "#angular/core";
import {Observable} from "rxjs/Observable";
import {Storage} from "#ionic/storage";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(public _storage: Storage) {
_storage.get('myToken').then((val) => {
console.log('Your age is', val);
});
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const changedReq = req.clone({headers: req.headers.set('Authorization', this.val)});
return next.handle(changedReq);
}
}
Caching the token in the interceptor is a bad idea because if the token changes the interceptor will not be aware of those changes.
// Don't do this.
token: string;
constructor(private storage: Storage) {
this.storage.get('token').then((res) => {
this.token = res;
})
}
If you want to use Ionic Storage and the interceptor together you can do so by using Observable.flatMap like so...
app.module.ts
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
SecurityStorageService
]
AuthInterceptor.ts
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private securityStorageService: SecurityStorageService
) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// This method gets a little tricky because the security token is behind a
// promise (which we convert to an observable). So we need to concat the
// observables.
// 1. Get the token then use .map to return a request with the token populated in the header.
// 2. Use .flatMap to concat the tokenObservable and next (httpHandler)
// 3. .do will execute when the request returns
const tokenObservable = this.securityStorageService.getSecurityTokenAsObservable().map(token => {
return request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
});
return tokenObservable.flatMap((req) => {
return next.handle(req).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff to the response here
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
// not authorized error .. do something
}
}
});
})
}
security-storage-service.ts
You technically don't need this service, but you shouldn't have Ionic Storage logic in your interceptor.
#Injectable()
export class SecurityStorageService {
constructor(private storage: Storage) {
}
getSecurityToken() {
return this.storage.get(StorageKeys.SecurityToken)
.then(
data => { return data },
error => console.error(error)
);
}
getSecurityTokenAsObservable() {
return Observable.fromPromise(this.getSecurityToken());
}
}
storage-keys.ts
export class StorageKeys {
public static readonly SecurityToken: string = "SecurityToken";
}
For anyone who comes across this like me and is using rxjs >=5.5.0 then you can just do:
auth-interceptor.ts
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.authService.getToken()).pipe(mergeMap((token) => {
const changedReq = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(changedReq);
}));
}
auth-service.ts
public async getToken() {
return await this.storage.get('ACCESS_TOKEN');
}
I used Http Restful API at Angular2, but appear the following warning message.
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
Please tell me how to do that.
http_restful_service.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class HTTPRestfulService {
constructor(private _http: Http) {}
getAllProjectName() {
var headers = new Headers();
headers.append('Content-Type','charset=uft-8');
return
this._http.get('http://localhost/api/database/',
{headers: headers})
.map(res => res.json());
}
}
backstage_view.component.ts
import { Component, OnInit } from '#angular/core';
import { HTTPRestfulService } from './../../../service/http_restful_service';
#Component({
moduleId: module.id,
selector: 'backstage_view',
templateUrl: './backstage_view.component.html',
styleUrls: ['./backstage_view.component.css']
})
export class BackstageViewComponent implements OnInit {
allProjects: string;
constructor(private _restfulapi: HTTPRestfulService) {}
ngOnInit() {
this._restfulapi.getAllProjectName()
.subscribe(
data => this.allProjects = data,
error => console.log(error),
);
}
}
Why can't you pass the content-type as 'application/json' format,
let url= `http://localhost/api/database/`;
let headers = new Headers();
headers.append('Content-Type','application/json');
let params = new URLSearchParams;
params.append('id', id);
params.append('user_id', user_id);
return this.authHttp.post( url, { headers:headers, search:params })
.map(res => res.json());
I am trying to get a product from a local server using an angular2 rest service. When I do the GET I get the following error. I can get the item from the server using the Insomnia rest client so I know the issue is not with the server. i've also checked the url and made sure there's no errors there. Any idea what else I can check? i'm using ng-cli to run the app...
my error:
http://10.60.160.34/BRMServices/WebEnquiry//POSEnquiry/293
Failed to load resource: net::ERR_CONNECTION_RESET
app.component.ts:32
failureServer error
my rest service:
import { Injectable } from '#angular/core';
import { Http, Headers, Response, RequestOptions } from "#angular/http";
import { Observable } from "rxjs/Rx";
import { ProductModel } from "../models/product.model";
//import 'rxjs/add/operator/map';
//import 'rxjs/add/operator/catch';
//import 'rxjs/add/observable/throw'
#Injectable()
export class RestService {
public API_URL: string = "http://10.60.160.34/BRMServices/WebEnquiry/";
private headers: Headers;
private options: RequestOptions;
constructor(private http: Http){
this.init();
}
init() {
this.headers = new Headers({ 'Content-Type': 'application/json' });
this.options = new RequestOptions({ headers: this.headers });
}
getProduct(barcode: string): Observable<ProductModel> {
return this.http.get(this.API_URL + "/POSEnquiry/" + barcode, this.options)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
my app.component.ts:
import { Component } from '#angular/core';
import { RestService } from "./services/rest.service";
import { ProductModel } from "./models/product.model";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
product: ProductModel;
constructor(private restService: RestService){}
submitBarcode(barcode: HTMLInputElement){
this.restService.getProduct(barcode.value)
.subscribe((res) => {
//product = res;
console.log(res);
}, (res) => {
console.log("failure" + res);
});
//console.log("product: " + product);
}
}
It turned out to be the RequestOptions variable. When I replaced options with headers in the get request it worked with no issues...