I'm trying to build an app with ionic that reads data from a local `.json' file and uses this data to fill a page. But I'm already struggling with importing the file into the page. What I currently have is:
import { Component } from "#angular/core";
interface Entry {
name: string,
telephone: string
}
interface EntryList {
entryList: Array<Entry>;
}
#Component({
selector: 'page-list',
templateUrl: 'list.html'
})
export class ListPage {
entryList: EntryList;
constructor() {
this.load_entries();
};
load_entries () {
this.entryList = JSON.parse(
// ?
)
};
}
The .json file contains entries like:
[
{"name": "Person A","telephone": "1234"},
{"name": "Person B","telephone": "12345"}
]
I don't know how to proceed from here on. What's the right way to get my data into the app?
Please try this:
constructor(public http: HttpClient) {
this.load_entries();
};
load_entries(filePath: string) { //filePath: 'assets/test.json'
this.http
.get(filePath)
.subscribe((data) => {
console.log(data);
});
}
Of course, you have to import HttpClient first.
import { HttpClient } from '#angular/common/http';
Related
I tried to get json from tne internal json file within angular.
with this service (village.service):
import { Injectable, OnInit } from '#angular/core';
import { Http, Response } from '#angular/http';
import { environment } from '../../environments/environment';
import { Observable } from 'rxjs'
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class RecordsService {
data: any;
constructor(private http: Http) { }
getVillages(id) {
return this.http.get('../assets/data/villages.json')
.map(data => {
this.data = data.json();
return data.json();
}, err => {
if (err) {
return err.json();
}
});
}
}
and under commponet i put the:
ngOnInit() {
this.getVillages();
....
}
and here to load as the chain dropdown
onSubDistrictSelected(subDistrictId: number) {
if (subDistrictId) {
this.onLoading.emit(true);
this.customer.subDistrict = this.subDistricts.filter(c => (c.id == subDistrictId))[0].name;
this.customer.sdid = subDistrictId;
this.customer.subDistrictId = subDistrictId;
this.villages = this.getVillages().filter((item) => {
return item.subDistrictId === Number(subDistrictId)
});
this.onLoading.emit(false);
}
}
I got error when compile said: this.getVillages is not function, But is working correctly if i put the json value inside the component file:
getVillages() {
return [
{ json_data}
]
}
What I want to achieved is I want to used the JSon file instead put directly inside the commponet.
Thanks,
getVillages is a method in service, so you need to instantiate the service before you use it.
First you need to provide the RecordsService in a module, like,
app.module.ts
...
providers : [
RecordsService
]
...
And in your component,
abc.component.ts
constructor(public recordService : RecordsService) {
}
ngOnInit() {
this.recordService.getVillages();
}
Let me know if you still get the error or have some different error.
EDIT:
getVillages() is returning an Observable, so you need to subscribe in order to use the data returned.
this.recordService.getVillages().subscribe( data => {
console.log(data);
} )
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
I am not sure if I have phrased this question correctly, so I apologize for the clunky wording. I am relatively new to angular but am pretty comfortable with making HTTP requests and working with the data in other frameworks (like VueJS). I am beginning to understand the Observables that angular uses. I am trying to make a blog application, and have an express backend that has the JSON for the blog posts.
In my post.service.ts I have:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable, of } from 'rxjs';
import { Post } from '../post';
#Injectable({
providedIn: 'root'
})
export class PostService {
private apiUrl = 'http://localhost:8081/posts';
getPosts(): Observable<Post[]> {
return this.http.get<Post[]>(this.apiUrl);
}
constructor( private http: HttpClient,
private postService: PostService ) { }
}
And then I want to list all the posts in my post-list.component.ts:
import { Component, OnInit } from '#angular/core';
import { PostService } from '../../services/post.service'
import { Post } from '../../post';
#Component({
selector: 'app-post-list',
templateUrl: './post-list.component.html',
styleUrls: ['./post-list.component.css']
})
export class PostListComponent implements OnInit {
public posts = [];
constructor(private postService: PostService) { }
ngOnInit() {
this.postService.getPosts()
.subscribe(data => this.posts = data);
}
}
But the posts array becomes an object and i'm not sure how to use it as an array. If I try to use the *ngFor method, I get an error. The page shows [object Object] if I put {{posts}} in the html. If i do {{posts | json}} it shows the actual JSON, but I still cannot iterate through it.
This is what the json looks like:
{
"posts": [
{
"_id": "5b04b269fde3ca29b35ffc3e",
"name": "Mike",
"title": "Stuff",
"post": "This is a post about stuff"
},
{
"_id": "5b04b24dfde3ca29b35ffc3d",
"name": "OtherUser",
"title": "New Post Test",
"post": "This is a test post"
},
{
"_id": "5b02ed783aa641758c08e601",
"name": "Emerjawn",
"title": "Post"
}
]
}
Before I try to setup CRUD for this application, I want to simply figure out how to display the data which I still cannot do and it is driving me insane. Thank you in advance for the help.
Your return JSON is an object which has field posts holding your needed array data so just take posts field from your server response and render such array of posts. Something like this:
ngOnInit() {
this.postService.getPosts()
.subscribe(data => this.posts = data.posts);
}
For better typing you can always specify your variable type i.e. public posts: Post[] then you will have type checking while coding.
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);
}
I want to display a line chart from JSON data. I have used angular2-highcharts. The problem is that the chart is displayed without data. I think that the issue is from extracting data from JSON.
The JSON format looks like this:
[{"_id" : ObjectId("59049a7b223f1e21ee4ee23b"),"amount" : 1,"date" :
"Mon, 18 Dec 1995 18:28:35 GMT"},{"_id" :
ObjectId("59049a7b223f1e21ee4ee23b"),"amount" : 1,"date" : "Mon, 18
Dec 1995 19:28:35 GMT"}]
I need only the "amount" in the X value and the "date" in the Y value.
Here is my code
ChartistJs.service.js
import {Injectable} from '#angular/core';
import { Headers, Http, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Data } from "./Data";
import 'rxjs/add/operator/toPromise';
private Url ='http://localhost:3000/transfer/chart';
constructor (private http: Http) {}
getData(){
return this.http.get(this.Url)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
ChartistJs.component.ts
import {Component} from '#angular/core';
import {ChartistJsService} from './chartistJs.service';
import 'style-loader!./chartistJs.scss';
import { Observable } from "rxjs/Observable";
import { ChartModule } from 'angular2-highcharts';
import 'rxjs/Rx';
import {Observer} from 'rxjs/Observer';
import {Http, Jsonp} from '#angular/http';
#Component({
selector: 'chartist-js',
template: `
<chart [options]="options"></chart>
`,
providers : [ChartistJsService]
})
export class ChartistJs {
options: Object;
constructor(private _chartistJsService:ChartistJsService) {
var chartData = this._chartistJsService.getData();
this.options = {
title : { text : 'simple chart' },
xAxis: {
type: 'category'
},
series: [{
data: chartData
}]
};
}
}
Can you help me how to deal with JSON data in Angular 2?
As Pankaj points out you are trying to pass a promise as the data, not the actual data that the promise eventually resolves to. More broadly, though, you aren't really using the tooling that Angular provides for dealing with HTTP.
In general, I would recommend that you:
Get used to dealing with observables, which is what Angular uses natively, rather than converting everything back to promises (although I think they still show this in the docs); and
Lean into the asynchronous nature of the observables, using the AsyncPipe to resolve them into your templates and the objects that RxJS provides to manipulate the data flow.
More specifically, here's one way you could implement what you're currently trying to.
Service:
#Injectable()
class DataService {
// acts as a pipe for the data that you can push new items into
private dataSubject = ReplaySubject(1);
// takes the subject and exposes the result, read-only
chartData$ = this.dataSubject.asObservable();
constructor (private http: Http) {}
getData() {
// GETs the data and pushes it into the subject
this.http.get('http://localhost:3000/transfer/chart')
.map(response => response.json())
.subscribe(data => this.dataSubject.next(data));
}
}
Component:
#Component({
... ,
// resolves the chart options asynchronously in the template
template: `
<chart [options]="chartOptions$ | async"></chart>
`
})
export class MyChartComponent implements OnInit {
chartOptions$: Observable<any>;
constructor(dataService: DataService) {
// creates a new observable of the chart options
this.chartOptions$ = this.dataService.chartData$
.map(data => this.createChartOptions(data));
}
ngOnInit() {
// triggers a fetch of the data to feed the observable
this.dataService.getData();
}
private createChartOptions(data) {
return {
title: { text: 'simple chart' },
xAxis: { type: 'category' },
series: [{ data: data }],
};
}
}
You will probably need to do more to the JSON than just pass it as the series.data, but this hopefully gives you an idea of how to leverage the stream of events an observable can provide. I've written more about this on my blog, including a follow-up article on testing.
Also note that your components shouldn't be importing anything from '#angular/http' - leave that to the services, use them as a layer of abstraction from the source of the data - and you can load providers at the module, rather than component, level.
Actually chartData variable does hold Promise returned by getData method. Where you should keep .then over the getData method calla and assign options with chartData like shown below.
It would be more better if you can do the same in ngOnInit lifecycle event.
Code
export class ChartistJs {
options: Object;
constructor(private _chartistJsService: ChartistJsService) {}
ngOnInit() {
this._chartistJsService.getData().then(
(data) => {
this.options = {
title: {
text: 'simple chart'
},
xAxis: {
type: 'category'
},
series: [{
data: data
}]
};
}
);
}
}