Angular - Unable to print json data in HTML page using *ngFor - json

I am new to angular. I have created a services class that returns a product details in json format.
api.service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class ApiService {
constructor(private http: Http) { }
fetchData() {
return this.http.get('http://funiks.com/qbook/api/productmasterjson.php').map(
(response) => response.json()
).subscribe(
(data) => data
)
}
}
Now i called this service in component class
api.component.ts
import { Component, OnInit } from '#angular/core';
import { ApiService } from '../api.service';
#Component({
selector: 'app-api',
templateUrl: './api.component.html',
styleUrls: ['./api.component.css']
})
export class ApiComponent implements OnInit {
public details;
constructor(private api:ApiService) { }
ngOnInit() {
this.details = this.api.fetchData();
console.log(this.details);
}
}
Now i want to print all the data in HTML page. This is what i have tried to print the json data
<tr *ngFor="let d of details">
<td>{{d.CATEGORY}}</td>
<td>{{d.HSN}}</td>
<td>{{d.ID}}</td>
<td>{{d.NAME}}</td>
<td>{{d.POSTINGHEAD}}</td>
<td>{{d.PRODUCTSERVICE}}</td>
<td>{{d.RATE}}</td>
<td>{{d.SACCODE}}</td>
<td>{{d.TAX_CONNECTED}}</td>
<td>{{d.TYPE}}</td>
<td>{{d.UNIT}}</td>
</tr>
But unfortunately it throws as error and error is like
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

Your component doesn't know the type of the fetchData, you should type it with
fetchData():Observable<Product[]> {
You shouldn't subscribe to your observable in fetchData(), just return the observable
fetchData():Observable<Product[]> {
return this.http.get('http://funiks.com/qbook/api/productmasterjson.php')
.map((response) => response.json()
)
}
In your component, subscribe to the observable and type details
details: Product[];
ngOnInit() {
this.api.fetchData().subscribe(data => this.details = data);
console.log(this.details);
}

You need to declare your public details as an array first of all
public details: any[];
Before your async request returns anything, your template doesn't know anything about the datatype of details unless you specify it.
I think that's why you are getting such error.
Cannot find a differ supporting object '[object Object]' of type
'object'. NgFor only supports binding to Iterables such as Arrays.
Also, put your subscribe part inside your component code

In your ngOnInit, you don't need to assign the return value to this.details as the when you are making get call the requests will have observable subscription. You will get a response in observable success so setting this.details value in success is needed as follows:
ngOnInit() {
this.api.fetchData().subscribe(response => this.details = response;);
console.log(this.details);
}

Related

NgFor not being passed an array

Ive tried searching for a solution to this, but I cant find anything less than 3 or 4 years old and those dont map to my problem well. I know what the issue is from the error, but cant seem to track it down, although I general idea that I will note in my description below:
I need to generate a menu from an array of json elements in the following format:
{
"body": [{
"coursename": "introto1",
"course-lesson-name": "Welcome to One! "
}, {
"coursename": "introto2",
"course-lesson-name": "What is One?"
}, {
"coursename": "introto2",
"course-lesson-name": "What Can We do with One?"
}]
}
This response is coming from AWS API gateway and I have set up the following service to handle the call:
menus.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class MenusService {
constructor(private http: HttpClient) { }
getLinks(){
return this.http.get('api address');
}
}
Here is the component that uses the services:
navigation.component.ts
import { Component, OnInit } from '#angular/core';
import { MenusService } from './../menus.service';
#Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {
links;
constructor(private menusService: MenusService,) { }
ngOnInit(){
this.links = this.menusService.getLinks();
}
}
and here is the component view:
navigation.component.html
<div>
<div class="col-sm-4" *ngFor="let links of links | async">
<a>{{links['course-lesson-name']}}</a>
</div>
</div>
I suspect my issue is in the service and the way Im establishing the get call:
return this.http.get('api address');
What am I missing here?
Here is the error for reference:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'.
NgFor only supports binding to Iterables such as Arrays.
I bet this.links resolves into an object and not an array.
Do this in your ngOnInit:
ngOnInit(){
this.links = this.menusService.getLinks();
this.links.subscribe(data => console.log(data)); // ensure data here is an array and not an object with `{ body: [....] }`
}
If it is an object like mentioned previously, in your service, try:
getLinks(){
return this.http.get('api address').pipe(
map(res => res.body),
);
}
You can also do that in the component level too but just be sure to get a handle on the array and not on the object for the *ngFor.

Argument of type 'Object' is not assignable to parameter of type 'JSON' Httpclient GET

Hello i am working on an Angular 6 + Flask application and I have this issue:
error TS2345: Argument of type 'Object' is not assignable to parameter of type 'JSON'.
when my code does that :
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { MessageService } from '../shared/message.service';
#Component({
selector: 'app-network-monitorer',
templateUrl: './network-monitorer.component.html',
styleUrls: ['./network-monitorer.component.css']
})
export class NetworkMonitorerComponent implements OnInit {
mqttMessageData : JSON[]=[];
coapMessageData : JSON[]=[];
xmppMessageData : JSON[]=[];
constructor(private httpClient: HttpClient, private messageService:MessageService) { }
ngOnInit() {
setInterval(()=>{
this.getMqttMessages(); },2000);
}
getMqttMessages() {
this.httpClient.get('http://127.0.0.1:5002/messages/mqtt').subscribe(data => {
this.mqttMessageData.push(data);
console.log("message :")
console.log(this.mqttMessageData.length())
console.log(data);
});
}
So basically when the component is loading i make a request to my python server to fetch some data which are returned to the client in JSON, but angular seems to think that 'data' is type of Object so i can't add it to my list of JSON
You'll have to cast it:
this.httpClient.get<JSON[]>('http://127.0.0.1:5002/messages/mqtt').subscribe(data => {
You'll need to convert the data to JSON.
Try using data.json as demonstrated below.
getMqttMessages() {
this.httpClient.get('http://127.0.0.1:5002/messages/mqtt').subscribe(data => {
this.mqttMessageData.push(data.json);
console.log("message :")
console.log(this.mqttMessageData.length())
console.log(data);
});
}

Angular2: json does not exist on type object

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]);
}

Angular 4 get data from github api

I trying getting my last commit from github. I used for this github api.
But I get error:
Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays."
I can getting data from simple json, and I used service and code like below, but now this not work for me.
Link to json:
JSON
If I getteing data from this JSON, then I don't getting error, and I display what I want.
My githubservice:
import { Injectable } from '#angular/core';
import { Http, Response, HttpModule } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { IpostsGithub } from './ipostsGithub'
#Injectable()
export class GithubService {
private _postsURL = "https://api.github.com/repos/objectprogr/Dashboard/git/refs/heads/v1";
constructor(private http: Http) {
}
getPosts(): Observable<IpostsGithub[]> {
return this.http
.get(this._postsURL)
.map((response: Response) => {
return <IpostsGithub[]>response.json();
})
}
private handleError(error: Response) {
return Observable.throw(error.statusText);
}
}
github component:
import { Component, OnInit } from '#angular/core';
import { GithubService } from './github.service';
import { IpostsGithub } from './ipostsGithub';
#Component({
selector: 'app-github',
templateUrl: './github.component.html',
styleUrls: ['./github.component.css'],
providers: [ GithubService]
})
export class GithubComponent implements OnInit {
_postsArray: IpostsGithub[];
user: string;
constructor(private githubService: GithubService, ) {
}
getPost(): void {
this.githubService.getPosts()
.subscribe(
resultArray => this._postsArray= resultArray,
error => console.log("Error :: " + error)
)
}
ngOnInit(): void {
this.getPost();
}
}
And html:
<table class="table">
<thead>
<th>1</th>
</thead>
<tbody>
<tr *ngFor="let post of _postsArray">
<td>{{post.message}}</td>
</tr>
</tbody>
</table>
This is code from error which I getting and, which I found o browser console:
_postsArray: […]
0: {…}
object: {…}
sha: "f0814bea75841ef7488552d29c6e1b8ad849f558"
type: "commit"
url: "https://api.github.com/repos/objectprogr/Dashboard/git/commits/f0814bea75841ef7488552d29c6e1b8ad849f558"
__proto__: Object { … }
ref: "refs/heads/v1"
url: "https://api.github.com/repos/objectprogr/Dashboard/git/refs/heads/v1"
And I dont have idea, how to fixed it?
Sounds like the API returns an object of objects, ngFor only works with iterables such as an array.
Seems like you are getting an Object instead of an Array, and you want to loop over that? Correct me if I'm wrong.
If that's the case this is how you would go about it:
in your .ts file
export class SomeClass {
Object: Object;
constructor() {
...
}
}
In your .html
<div *ngFor="let item of Object.keys(yourObject); let i = index;">
{{item}}={{yourObject[item]}}
</div>

Ionic 2 - Turning HTTP GET JSON Response into an array of items

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 || { };
});
}
}