How to get json file from HttpClient? - json

I am trying to get a json file from HttpClient, but I get a error when I add .subscribe
imports:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpClientModule } from '#angular/common/http';
import { HttpModule, Request, Response, Headers, Http } from '#angular/http';
import { Observable } from 'rxjs';
My code:
When I add .subscribe (yellow marked in image) I got the following error. What does it mean?
Object { _body: error, status: 0, ok: false, statusText: "", headers:
Object, type: 3, url: null }

If you want to make something very clear and organised you should create a service in angular and call the service from your component.
Like this for example:
Service.ts:
import { Injectable } from "#angular/core";
import { Observable, throwError } from "rxjs";
import {
HttpClient,
HttpHeaders,
HttpErrorResponse
} from "#angular/common/http";
import { catchError, map } from "rxjs/operators";
// Set the http options
const httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json", "Authorization": "c31z" })
};
#Injectable({
providedIn: "root"
/**
* Service to call all the API
*/
export class ApiService {
constructor(private http: HttpClient) {}
/**
* Function to handle error when the server return an error
*
* #param error
*/
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error("An error occurred:", error.error.message);
} else {
// The backend returned an unsuccessful response code. The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` + `body was: ${error.error}`
);
}
// return an observable with a user-facing error message
return throwError(error);
}
/**
* Function to extract the data when the server return some
*
* #param res
*/
private extractData(res: Response) {
let body = res;
return body || {};
}
/**
* Function to GET what you want
*
* #param url
*/
public getListOfGroup(url: string): Observable<any> {
// Call the http GET
return this.http.get(url, httpOptions).pipe(
map(this.extractData),
catchError(this.handleError)
);
}
}
Component.ts:
import { Component, OnInit } from "#angular/core";
import { ApiService } from "../../services/api.service";
#Component({
selector: "app-example",
templateUrl: "./example.component.html",
styleUrls: ["./example.component.css"]
})
export class ExampleComponent implements OnInit{
url = "/url/path/to/your/server";
constructor(private api: ApiService) {}
ngOnInit() {
this.api
.getListOfGroup(url)
.subscribe(
data => {
console.log(data);
},
err => {
console.log(err);
}
);
}
}
My advice would be to follow the getting start of angular if not you will be quickly lost. Service tutorial angular

Related

How can I access the first element of JSON array data?

I'm using ionic as a front end and Laravel as a back end.
This is the returned JSON data from an API URL, I want to access just the first element which is a.jpg without anything else, I tried using filenames.[0] but it's just displaying [ which means that it's calling the first character not the first element of the array.
Here's the JSON data:
[{"filenames":"[\"a.jpg\",\"b.jpg\",\"c.jpg\"]"}]
Here's my .ts file
import { ApiLandingRecipesService} from '../api-landing-recipes.service'
#Component({
selector: 'app-landing-page',
templateUrl: './landing-page.page.html',
styleUrls: ['./landing-page.page.scss'],
})
export class LandingPagePage implements OnInit {
datauser: any[];
constructor( public api: ApiLandingRecipesService) { }
ngOnInit() {
this.getDataUser();
}
async getDataUser() {
await this.api.getDataUser()
.subscribe(res => {
console.log(res);
this.datauser =res;
console.log(this.datauser);
}, err => {
console.log(err);
});
}
and Here's my service file:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Observable, throwError } from 'rxjs';
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
const apiUrl = "https://example.com/showimages";
#Injectable({
providedIn: 'root'
})
export class ApiLandingRecipesService {
constructor(private http: HttpClient) { }
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError('Something bad happened; please try again later.');
}
private extractData(res: Response) {
let body = res;
return body || [] ; }
getDataUser(): Observable<any> {
return this.http.get(apiUrl, httpOptions).pipe(
map(this.extractData),
catchError(this.handleError));
}
}
It's because filenames is indeed a string (a json string representation of the array) and not an array.
Try converting the string into an array first.
JSON.parse(filenames)[0]
The value of filenames here is a string and not an array, which is why you're getting [ when you try to access the first element.
You probably need to parse the value, here's an example (assuming datauser) is the JSON data you've shown us.
let filename = JSON.parse(datauser[0].filenames)[0]

IONIC API Undefined

I have an IONIC APP with CORDOVA. I Just want to GET a JSON from an URL.
I Created a service call rest.service.ts
rest.service.ts
import { Injectable } from '#angular/core';
import { HTTP } from '#ionic-native/http/ngx';
#Injectable({
providedIn: 'root'
})
export class RestService {
BASE_URL = 'http://whatever.....';
constructor(public http: HTTP) {}
getProjects() {
const URL = this.BASE_URL + 'getProjects';
this.http.get(URL, {}, { 'Content-Type': 'application/json' })
.then(answer => {
return JSON.parse(answer.data);
})
.catch(error => {
console.log(error.status);
console.log(error.error); // error message as string
console.log(error.headers);
});
}
}
Here in this file I can see the info. If I insert something like...
console.log(JSON.parse(answer.data));
I can see the results in JSON just as I Want.
The problem is when I try to use this methods in other files...
otherpage.page.ts
import { Platform } from '#ionic/angular';
import { RestService } from './../rest.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-otherpage',
templateUrl: './otheropage .page.html',
styleUrls: ['./otherpage .page.scss']
})
export class OtherPage implements OnInit {
projects;
constructor(
public platform: Platform,
public rest: RestService,
) {
this.projects = this.rest.getProjects();
console.log(this.projects); // UNDEFINED
}
ngOnInit() { }
}
Here... this.projects... is undefined... ¿What is happening? I tried platform.ready, insert in ngOnInit... nothing works.
You need to modify the service and subscribe this service your page.
BASE_URL = 'http://whatever.....';
getProjects() {
const URL = this.BASE_URL + 'getProjects';
return this.http.get(URL, {}, { 'Content-Type': 'application/json' });
}
Subscribe this service observable in your page.ts file.
this.rest.getProjects().subscribe((answer)=>{
this.projects = JSON.parse(answer.data);
console.log(this.projects); // here you get the json
},error=>{
consoole.log(error)
});
Note:
console.log(this.projects); // UNDEFINED
Because this line executes before the http observable send the response, you need to subscribe that http observable to get the json.

I get a error while publishing a app. The error is property json does not exist on type object

when I try to test the app in Ionic serve command, I didn't get any error. But when i try to publish the app, I get the error as "property json does not exist on type object" . The error takes place during the transpile stage:
How to solve this problem? I tried with every possibility, but i didn't get my problem solved.
Home.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { WeatherProvider } from '../../providers/weather/weather';
import { Storage } from '#ionic/storage';
//import { Response } from '#angular/http';
//import 'rxjs/add/operator/map';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
weather:any;
location:{
city:string,
state:string
}
constructor(
public navCtrl: NavController,
private weatherProvider:WeatherProvider,
private storage: Storage) {
}
ionViewWillEnter(){
this.storage.get('location').then((val)=>{
if(val!=null){
this.location = JSON.parse(val);
}else{
this.location = {
city: 'Chennai',
state: 'TN'
}
}
this.weatherProvider.getWeather(this.location.city,this.location.state)
// .map((res: Response) => res.json() )
.subscribe(weather => {
this.weather = weather.current_observation;
});
});
}
}
Weather.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
//import { Response } from '#angular/http';
//import 'rxjs/add/operator/map';
//import 'rxjs/Rx';
#Injectable()
export class WeatherProvider {
apiKey = '6d3243fb22b01d0c';
url;
constructor(public http: HttpClient) {
console.log('Hello WeatherProvider Provider');
this.url = 'http://api.wunderground.com/api/'+this.apiKey+'/conditions/q';
}
getWeather(city, state){
return this.http.get(this.url+'/'+state+'/'+city+'.json')
// .map(res => res.json());
// .map((res: Response) => res.json() );
}
}
Typescript is all about typing. So you should state the type of object you'are receiving from the method getWeather. Start by creating a class Weather at the end of home.ts (look below)
class Weather {
current_observation: string;
}
and make this change:
this.weatherProvider.getWeather(this.location.city,this.location.state)
// .map((res: Response) => res.json() )
.subscribe((weather: Weather) => {
this.weather = weather.current_observation;
});
});
}
ionViewWillEnter(){
this.storage.get('location').then((val) => {
if(val != null){
this.location = JSON.parse(val);
} else{
this.location ={
city: 'miami',
state: 'FL'
}
}
//Try below code
this.weatherprovider.getweather(this.location.city, this.location.state).subscribe(result => {
let weather:any = result;
this.weather = weather.current_observation;
console.log(this.weather);
});
});
}

Unexpected token < in JSON at position 0 when attempt call ASP.NET controller

I'm found and read many post about this error but don't found analogous or similar issues.
Attempt get data from MVC controller using post in angular 2.
Controller:
[RoutePrefix("")]
public class CategoryController : ApiController
{
[HttpPost, Route("createNode")]
public object CreateNode([FromBody]string nodeText)
{
return Json( new { nodeText = "test"});
}
}
function in component
onclickCreateFolder(categoryName: string) {
this.categoryService.createNode(categoryName).then(result => {
});
angular-2 service
import { Injectable } from '#angular/core';
import { Http, RequestOptions, Request, RequestMethod, Headers } from '#angular/http';
import { BaseService } from '../../base/base.service'
import { CategoryViewModel } from '../model/category-tree.model';
import { TreeNode } from 'primeng/primeng';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class CategoryTreeService {
private apiUrl: string = '/';
constructor(private baseService: BaseService, private http: Http) {
}
createNode(nodeText: string): Promise<any> {
return this.baseService.post(this.apiUrl + "createNode", JSON.stringify({nodeText}));
}
}
I am using base service. Here is a part that initiate post request:
import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
import { Response, RequestOptionsArgs, ResponseContentType } from '#angular/http';
import { Http, RequestOptions, Request, RequestMethod, Headers } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';
#Injectable()
export class BaseService {
private headers: Headers = new Headers({ 'Content-Type': 'application/json; charset=utf-8', 'Data-Type': 'json' });
constructor(private http: Http, private router: Router) {
}
public post<T>(url: string, body: any, options?: RequestOptionsArgs): Promise<T> {
return this.http.post(url, body, this.mergeHeaders(options))
.toPromise()
.then(response => response.json() as T)
.catch(this.handleError.bind(this));
}
private mergeHeaders(options?: RequestOptionsArgs): RequestOptionsArgs {
let args = options || {};
args.headers = args.headers || this.headers;
return args;
}
public handleError(error: any) {
if (error.status == 400) {
switch (error.statusText) {
case "Authentication":
this.router.navigate(['/error/auth']);
break;
default:
return Promise.reject(error);
}
return;
}
return Promise.reject(error.toString());
}
}
I understand the reason for the error because in response i see my single html page. Also in debug i see that method in ASP.NET controller is not called. Maybe error in ASP.NET MVC routing?
Already spent a lot of time, but I still do not understand where the error is. What i'm doing wrong?

Parse Json from file

I have service to parse json
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class TestService {
private tsUrl = './../Test/test.json';
data: Object;
constructor(private http: Http) {}
getTest(): Observable<any> {
return this.http.get(this.tsUrl)
.map(res => res.json());
}
}
But When I call this in my component
private p: any;
constructor(private testService : TestService ) {
this.p =this.testService .getTest().subscribe(
data => {
console.log(data);
};
console.log(this.p);
}
it logs:
What can I do?
And am I doing parse from json file right? File path is correct
#echonax solved my problem but now I see this error message