I am reading data from a JSON, which is one a server and it updates regularly and changes. I need to be able to read this JSON from the server so that I display the most up to date information on my web page.
Currently, the to be able to read the JSONs they are stored within the same project folder as my angular project. (This was because they were not set up on the server when I started).
This is how I currently import the JSON to be able to read it:
import jsonInfo from '../../../info.json'
I thought I would be able to change the file link to the server address, like so:
import jsonInfo from 'http://servername/folder/info.json'
But, VSCode gives me an error: Cannot find module 'http://servername/folder/info.json'
This is definitely the location of the JSON I am trying to load because when I click the link it takes me to the JSON and displays it.
My question is, how do I import the JSON into my .ts from a server so that I can keep getting the updated information from the JSON?
JSON file on a server is just like any other web resource you would try to access (like an API endpoint, for example).
So you should use built in angular http client to access this JSON file.
For example:
import { HttpClient } from '#angular/common/http';
export class SomeService {
constructor(private http: HttpClient) { }
getInfo() {
return this.http.get('http://servername/folder/info.json');
}
}
//...
export class SomeComponent implements OnInit {
info: any;
constructor(private someService: SomeService) {}
ngOnInit() {
this.someService.getInfo().subscribe(info => this.info = info)
}
}
Use HttpClient get method.
this.httpClient.get('http://servername/folder/info.json').subscribe(data => {
// your logic
})
You can use HttpClient and do like as shown below
Working Demo
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular';
data = [];
apiUrl = 'http://servername/folder/info.json';
GetData() {
this.http.get<any[]>(this.apiUrl)
.subscribe(data => {
this.data = data;
});
}
ClearData() {
this.data = [];
}
constructor(private http: HttpClient) {}
ngOnInit() {}
}
Related
I tried to make a practice task-app and basically I have to get all the task data from a json server. I'd like to display it in the browser console first but the data won't show up and it shows an error. I followed all the steps from the tutorial video I've watched but still I'm getting the error.
console error
This is my service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root',
})
export class RestapiService {
constructor(private http: HttpClient) {}
getTasks() {
return this.http.get('http://localhost:3000/tasks');
}
}
My taskdisplay.component.ts
import { Component, OnInit } from '#angular/core';
import { RestapiService } from 'src/app/services/restapi.service';
#Component({
selector: 'app-taskdisplay',
templateUrl: './taskdisplay.component.html',
styleUrls: ['./taskdisplay.component.css'],
})
export class TaskdisplayComponent implements OnInit {
constructor(private service: RestapiService) {}
ngOnInit(): void {
this.getallTasks();
}
userTasks: any = [];
getallTasks() {
this.service.getTasks().subscribe((result) => {
this.userTasks = result;
console.log(this.userTasks);
});
}
}
Your setting of the server url should not be done in the request. In the error message you see the url getting parsed in a weird way.
Instead make the call as such http.get('tasks') and otherwise, follow the answer as described in this post:
How do I set the baseUrl for Angular HttpClient?
I've read every other article or post about this I can find. I cannot for the life of me figure out where I'm going wrong with this simple task. (Specifically following this example.) I must be doing something obviously stupid but I've been looking at this so long I can't see it.
I have a json file called isRecognized.json in assets/mockData. I've added the mockData directory to my webpack config file so it's included in the /dist directory. If I go to http:localhost:4200/assets/mockData/isRecognized.json I'm able to see the file, so I know it's available.
However, when I try to retrieve the file using HTTP Client, it throws a 404 no matter what I try.
EDIT: I'm using Webpack, not Angular CLI.
app.component.ts
import { MyService } from './services/my.service';
import { Component, OnInit, Renderer2 } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
/*
* Main app component that houses all views.
*/
#Component({
selector: 'app-comp',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
constructor(
private route: ActivatedRoute, private service: MyService
) {}
ngOnInit() {
this.service.isRecognized();
}
}
my.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
#Injectable()
export class MyService {
constructor(private http: HttpClient) { }
isRecognized() {
this.getJSON('isRecognized').subscribe(data => {
console.log(data);
});
}
getJSON(fileName): Observable<any> {
return this.http.get('http://localhost:4200/assets/mockData/' + fileName + '.json');
}
}
The error I get in the browser console is:
AppComponent_Host.ngfactory.js? [sm]:1 ERROR Error: [object Object]
at viewWrappedDebugError (core.js:9795)
at callWithDebugContext (core.js:15101)
at Object.debugCheckAndUpdateView [as checkAndUpdateView] (core.js:14628)
at ViewRef_.webpackJsonp../node_modules/#angular/core/esm5/core.js.ViewRef_.detectChanges (core.js:11605)
at core.js:5913
at Array.forEach (<anonymous>)
at ApplicationRef.webpackJsonp../node_modules/#angular/core/esm5/core.js.ApplicationRef.tick (core.js:5913)
at core.js:5746
at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
at Object.onInvoke (core.js:4756)
If I debug the error, I can see the body of the error is:
I have this working successfully in my app just using a URL like this:
private productUrl = 'api/products/products.json';
Notice that it does not have the localhost part of the path.
So try something more like this:
'assets/mockData/' + fileName + '.json'
Also ensure that your angular.json has the path listed under assets:
"assets": [
"src/favicon.ico",
"src/assets",
"src/api"
],
NOTE: I also didn't do anything to modify my webpack configuration. (But I'm using the CLI.)
If you want to look at some working code that accesses a json file, I have an example here:
https://stackblitz.com/edit/github-gettingstarted-deborahk
I would suggest subscribing in the component, and returning an Observable from the service:
Service:
#Injectable()
export class MyService {
constructor(private http: HttpClient) { }
isRecognized(fileName): Observable<any> {
return this.http.get('http://localhost:4200/assets/mockData/' + fileName + '.json');
}
}
Component:
export class AppComponent implements OnInit {
constructor(
private route: ActivatedRoute, private service: MyService
) {}
ngOnInit() {
this.service.isRecognized(fileName)
.subscribe(data => {
console.log(data);
});
}
}
While this might not be a direct solution to your specific problem, you should take a look at the npm package json-server. I use it to mock the API when developing and testing the client.
json-server npm
It will run a node web server on port 3000, and is really easy to use right out of the box.
See this tutorial example of how to use it:
Mock api with json-server
There might be better examples and setting up the proxy isn't necessary, but should be good enough.
Finally figured out the answer! I had this in my app.module.ts file as an import:
InMemoryWebApiModule.forRoot(InMemoryDataService, { dataEncapsulation: false })
Removing this fixed the issue immediately.
This should be the simplest thing. I have a component that calls a service that imports a local JSON directly (see Import JSON directly with Angular 7)
It reads the JSON contents fine, but the pages property is undefined. I think I set everything up based on the StackBlitz in that link, there doesn't seem to be much to it. There isn't any HTML yet, this is all just via the console. It's in app.component.html.
Reading local json files json.service.ts:14
[{…}]0: {name: "Home"}length: 1__proto__: Array(0) json.service.ts:15
undefined home.component.ts:31
json.service.ts:
import { Injectable } from '#angular/core';
import SampleJson from '../assets/SampleJson.json';
export interface JsonInterface {
name: any;
}
#Injectable()
export class JsonService {
ngOnInit() {
console.log('Reading local json files');
console.log(SampleJson);
}
}
home.component.ts:
import { JsonService, JsonInterface } from '../json.service';
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(service: JsonService) {
service.ngOnInit();
};
#Input() pages: JsonInterface;
ngOnInit() {
console.log(this.pages);
}
}
Sample.json
{ "name":"Home" }
If I understand your log correctly, it works as expected:
constructor(service: JsonService) {
service.ngOnInit();
};
You request the service and you get an instance. Then you call ngOnInit:
ngOnInit() {
console.log('Reading local json files');
console.log(SampleJson);
}
Now it logs the "reading…" and the content of your json file.
ngOnInit() {
console.log(this.pages);
}
Then you log this.pages which is empty. You never filled it. You never did anything with your service or the data loaded in your service.
I think what you want is something like this
export class JsonService {
getPages() { return SampleJson; }
}
and in your component:
constructor(private service: JsonService) {}
ngOnInit() {
this.pages = this.service.getPages();
console.log(this.pages);
}
The sample code is not tested but I think you've got the point.
The problem is with pages. You have inly declared 'pages' as 'JsonInterface' which is only the type of 'pages' but never initialized with any value so it is undefined.. you need to write a function in Service as the above answer by #Christoph .
I hope you understand why this error occured and If you are not inputting a value to 'pages' from html you don't need to declare it as '#Input'.
I am beginner. I am not able to solve this problem. i have read the other errors but still i am not able to understand.
While i am doing .map or .subscribe to the service it gives me error like Property 'json' does not exist on type object.
This is my: continents.component.ts
import { Component, OnInit } from '#angular/core';
import { DataContinentsService } from '../../services/dataContinents.service';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-continents',
templateUrl: './continents.component.html',
styleUrls: ['./continents.component.css'],
providers: [DataContinentsService]
})
export class ContinentsComponent implements OnInit {
continent: any;
constructor(private dataContinentService: DataContinentsService) { }
public getContinentInfo() {
this.dataContinentService.getContinentDetail()
.map((response) => response.json())
.subscribe(res => this.continent = res.json()[0]);
}
ngOnInit() {}
}
This is my Service: DataContinentsService
import { Injectable } from '#angular/core';
import {HttpClientModule, HttpClient} from '#angular/common/http';
// import 'rxjs/add/operator/map';
#Injectable()
export class DataContinentsService {
constructor(private _http: HttpClient) {}
public getContinentDetail() {
const _url = 'http://restcountries.eu/rest/v2/name/india?fulltext=true';
return this._http.get(_url);
}
}
This is my Template: continents.component.html
<h1>Continents</h1>
<h3>Name: {{continent.name}}</h3>
<h3>Capital: {{continent.capital}}</h3>
<h3>Currency: {{continent.currencies[0].code}}</h3>
<button (click)="getContinentInfo()">get details</button>
I'm guessing that you've been reading some outdated documentation.
The old Http class used to return a response that did have a json() method.
The old Http class has been retired, and you are now properly using the HttpClient class. HttpClient's get() method returns an Observable of any - it maps the response's json to an object for you. Typically, you'd specify the type of the object, like so:
this.http.get<SomeObject>(url);
In lieu of that, you just get an Object.
In either case, there's no json() method on the returned object.
So, your service should do this:
public getContinentDetail(): Observable<Continent[]> {
const _url = 'http://restcountries.eu/rest/v2/name/india?fulltext=true';
return this._http.get<Continent[]>(_url);
}
you should subscribe something like this
this.dataContinentService.getContinentDetail().subscribe(continents: Continent[] =>
this.continent = continents[0]);
}
I am working on an app and am having difficulty using an API call to Eventbrite in a provider, parsing the JSON it returns, and inserting the data I want into an array.
Here is my provider (event-provider.ts):
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import {NativeStorage} from "ionic-native";
import 'rxjs/add/operator/map';
/*
Generated class for the EventProvider provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
#Injectable()
export class EventProvider {
constructor(public http: Http) {
console.log("Event Provider")
}
public getJsonData(){
return this.http.get('https://www.eventbriteapi.com/v3/events/search/?location.address=Atlanta&expand=organizer,venue&token=VMGQGYQUIO3IKNS75BD4').map(res => res.json().events);
}
//console.log('Hello EventProvider Provider');
}
And here is the event page in which I eventually will list the data (events.ts):
import { Component } from '#angular/core';
import {EventProvider} from '../../providers/event-provider';
import { NavController } from 'ionic-angular';
#Component({
selector: 'event-list',
templateUrl: 'events.html',
providers: [EventProvider]
})
export class EventsPage {
events = []
constructor(public navCtrl: NavController, private eventProvider: EventProvider) {
this.events = eventProvider.getJsonData();
}
}
For the above .ts file I am getting an error at this.events = eventProvider.getJsonData();. The error says: Type 'Observable' is not assignable to type 'any[]'. Property 'find' is missing in type 'Observable'. I do not really understand this error.
This is what the JSON response looks like: EventBrite
Basically, I want to add each event as an item to an array. The JSON response contains about 500 events.
I've just stuck at the moment an not sure if on on the right track. It is hard to debug my code because it is being tested in an iOS emulator and thus the console.log() doesn't work. Any tips on how to reach my goal of creating an array of events from the JSON response?
You need to subscribe to observables in order to make a request.
this.events = eventProvider.getJsonData();
should be something like:
eventProvider.getJsonData().subscribe((res)=>{
this.events = res.events;
});
And Also you need to return that json and assuming you always have event properties in the response:
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import {NativeStorage} from "ionic-native";
import 'rxjs/add/operator/map';
/*
Generated class for the EventProvider provider.
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
for more info on providers and Angular 2 DI.
*/
#Injectable()
export class EventProvider {
constructor(public http: Http) {
console.log("Event Provider")
}
public getJsonData(){
return this.http.get('yourUrl')
.map(res => {
let body = res.json();
return body.events || { };
});
}
}