Angular 4 get data from github api - json

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>

Related

Angular 'Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.'

I'm creating an Angular app which shows list of projects and list of users from postgresql database, but I'm having issues with showing list of users in html.
The problem is that Angular is considering my array as an object no matter what I do.
The same code worked for projects but didn't work for users.
This is my service:
import { environment } from "../../../environments/environment";
import { Observable } from 'rxjs';
import { Projet } from '../modele/projet.model';
import { Test } from '../modele/test.model';
import { HttpParams,HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { map } from 'rxjs/operators';
import { User } from '../modele/user.model';
import { Financement } from '../modele/financement.model';
#Injectable()
export class WebService {
constructor(private httpClient: HttpClient) { }
serverUrl: string = "http://localhost:8080/"
get(url: string): Observable<any> {
return this.httpClient.get(this.serverUrl + url);
}
}
The component :
import { Component, OnInit } from '#angular/core';
import { User } from '../../shared/modele/user.model';
import { Router } from '#angular/router';
import { WebService } from '../../shared/sevices/web.service';
import { FormGroup, FormBuilder, FormControl, Validators, Form } from '#angular/forms';
#Component({
selector: 'app-show-users',
templateUrl: './show-users.component.html',
styleUrls: ['./show-users.component.scss']
})
export class ShowUsersComponent implements OnInit {
ngOnInit(): void {
this.getData();
}
usersList: Array<User>
user: User
myForm: FormGroup;
constructor(private webService: WebService, private formBuilder: FormBuilder,private router: Router) { }
getData(): void {
this.webService.get("showUsers").subscribe(res => {
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
})
}
}
The html :
<tr *ngFor="let user of usersList">
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
</tr>
This is the server response :
server response
NB: the EXACT same code worked for the object PROJECT
You need to make sure that the variable you pass into *ngFor is an array. You can make sure of this with Array.from(v) and can also strip any keys of an Object that might be sent from the serverside with Object.values(v):
this.webService.get("showUsers").subscribe(res => {
this.usersList = Array.from(Object.values(res.data.body.data));
})
In my case, I have a simple approach, but I spent a lot of time. You could try this:
datas: any;
this.token = JSON.parse(window.localStorage.getItem('token'));
this.authService.getData(this.token.id).subscribe(data => {
this.datas = data;
})
In the HTML template just use this.datas.id, this.datas.username instead of an *ngFor
You don't need this code:
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
simply use:
this.userlist = res
Youe complete method:
this.webService.get("showUsers").subscribe(res => {
this.userlist = res
});

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.

Angular5 *ngfor not working, but there is no error

I'm facing a problem with Angular at the moment.
I want to read data from my server API and want to display it with *ngfor in a html document.
I can receive the data from the API, but i can't display it.
I took the example code from the tour of heroes tutorial and changed it:
The data gets through to my angular app. I can console.log it and see it in chrome development console.
I tried to display other data that I get from my api and it is working. You can see the data commented out in heroes.components.ts.
Who can help me with this?
If you want to see some more of the code like imports please tell me. But i guess everything needed imported as there are no error messages, i can get the data from my api and i can display some data (sadly not the data i need).
I tried several ideas to solve this from some other posts, but can't get it working.
Here are some Code Snippets:
This is my hero.service.ts
imports...
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { HttpResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { catchError, map, tap } from 'rxjs/operators';
import { Hero } from '../model/hero';
import { MessageService } from '../message.service';
import { Response } from '#angular/http/src/static_response';
getHeroes(): Observable<Hero[]> {
console.log("GET HEROES IN HEROES.SERVICE");
return this.http.get<Hero[]>(this.heroesUrl)
.pipe(
tap(Hero => console.log(`fetched heroes: `)),
catchError(this.handleError('getHeroes', []))
);
//I also tried to just use return this.http.get<Hero[]>(this.heroesUrl);
This is my
heroes.components.ts
import { Component, OnInit } from '#angular/core';
import { Hero } from '../../model/hero';
import { HeroService } from '../hero.service';
import { CommonModule } from '#angular/common';
import { Pipe } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { Response } from '#angular/http/src/static_response';
// For use of map
import 'rxjs/Rx';
#Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
heroes: Observable<Hero[]>;
// I tried to display some data
// heroes: any[] = [
// {
// "name": "Douglas Pace"
// }
// ];
constructor(private heroService: HeroService) { }
ngOnInit() {
this.getHeroes();
// undefined
console.log("ONINIT");
console.log(this.heroes);
}
getHeroes(): void {
console.log("GET HEROES IN HEROES.COMPONENT");
this.heroService.getHeroes()
.subscribe(
function(response: Hero[]) {
console.log("RESPONSE IN HEROES COMPONENT");
console.log(this.heroes);
var res = response["data"];
// console.log(res.json());
this.heroes = res;
console.log(this.heroes);
console.log(response["data"]);
},
function(error) {
console.log("Error happened" + error)
},
function() {
console.log("the subscription is completed")
//This shows me the right data.
console.log(this.heroes[5].id);
console.log(this.heroes[5].titel);
console.log(this.heroes[5].name);
console.log(this.heroes[5].vorname);
}
);
}
My html file:
<h2>My Heroes</h2>
<!-- <input type=text ng-model="hero"> -->
// I gave it a try with and without *ngIf="heroes"
<!-- only show the list IF the data is available -->
<div *ngIf="heroes">
<h3>Heroes are available and are displayed</h3>
<li *ngFor="let hero of heroes">
{{hero.name}}
</li>
</div>
<button (click)="button()">
Suchen
</button>
<div *ngIf="heroes">
<table class="heroes">
<tr>
<th>Id</th>
<th>Titel</th>
<th>Nachname</th>
<th>Vorname</th>
</tr>
//I tried async as the data is maybe not available from the
beginning. Also tried async on hero as heroes is created on init
and single heros are added with the function getHeroes();
<tr *ngFor='let hero of heroes | async'>
<a routerLink="/detail/{{hero.id}}">
<td>{{hero.id}}</td>
<td>{{hero.titel}}</td>
<td>{{hero.name}}</td>
<td>{{hero.vorname}}</td>
</a>
<button class="delete" title="delete hero"
(click)="delete(hero)">x</button>
</tr>
</table>
</div>
<pre>{{heroes | json}}</pre>
If got a hero interface. Should be my model. Only Last and First name are needed.
export interface Hero {
id?: string;
name: string;
titel?: string;
vorname: string;
}
The JSON I returned from my API. Online Json formatter says it is valid json.
{"status":"Success","data":
[{"id":"36","name":"Hero","vorname":"Super","titel":"Dr.",},
{"id":"34","name":"Man","Spider":"Ines","titel":""}],
"message":"Retrieved all HEROES"}
this.heroService.getHeroes()
.subscribe(
function(response: Hero[]) { }
Your problem could be here. Your response is an object with (let's say, interface):
interface DataResponse {
success: string;
data?: Hero[];
}
Because you set response: Hero[] and there's no data property in your Hero interface, response["data"] returns null and you'll never get your data. If you run response.data, you'll probably get an error saying data is not defined in Hero etc...
Change to the following:
this.heroService.getHeroes()
.subscribe((response: DataResponse) => {
this.heroes = response["data"];
});
Your code seems to be ok but i see an error in your json format here
"titel":"Dr.",},
try to remove the comma after Dr and give it a try
"titel":"Dr."},

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

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

Angular2:ERROR Error: InvalidPipeArgument: '' for pipe 'AsyncPipe' and Angular2:ERROR TypeError: Cannot read property 'dispose' of null

I am new to angular2, my target is to display the Json data which is returned from rest service, in my template, below is the Json data which is coming from rest service.
{"wellList":[{"country":"IDN","well":"Test","wellbore":"N","company":"Test","active":"N"},{"country":"IDN","well":"Test","wellbore":"N","company":"Test","active":"Y"},{"country":"IDN","well":"Test","wellbore":"N","company":"Test","active":"Y"},{"country":"IDN","well":"Test","wellbore":"N","company":"Test","active":"Y"},{"country":"IDN","well":"Test","wellbore":"N","company":"Test","active":"Y"}]}
The below is the code which i have written in my template:
<ul>
<li *ngFor="let well of wells | async">
<table>
<tr>
<th scope="col">Active</th>
<th scope="col">Company</th>
<th scope="col">Country</th>
<th scope="col">Well</th>
<th scope="col">Wellbore Indicator</th>
</tr>
<tr>
<td>{{well.active}}</td>
<td>{{well.company}}</td>
<td>{{well.country}}</td>
<td>{{well.well}}</td>
<td>{{well.wellbore}}</td>
</tr>
</table>
</li>
</ul>
But, no luck it is not working, giving the below two errors:
ERROR Error: InvalidPipeArgument: '' for pipe 'AsyncPipe'
at invalidPipeArgumentError (common.es5.js:2610)
at AsyncPipe.webpackJsonp.../../../common/#angular/common.es5.js.AsyncPipe._selectStrategy (common.es5.js:2755)
at AsyncPipe.webpackJsonp.../../../common/#angular/common.es5.js.AsyncPipe._subscribe (common.es5.js:2741)
at AsyncPipe.webpackJsonp.../../../common/#angular/common.es5.js.AsyncPipe
ERROR TypeError: Cannot read property 'dispose' of null
at AsyncPipe.webpackJsonp.../../../common/#angular/common.es5.js.AsyncPipe._dispose (common.es5.js:2761)
at AsyncPipe.webpackJsonp.../../../common/#angular/common.es5.js.AsyncPipe.transform (common.es5.js:2725)
Can anyone help me how to get rid of this
Component:
import { Component, OnInit } from '#angular/core';
import { UserService } from '../services/user.service';
import { User } from '../user/user';
import { Observable } from 'rxjs/Rx';
#Component({
selector: 'app-well',
templateUrl: './well.component.html',
styleUrls: ['./well.component.css'],
providers:[UserService]
})
export class WellComponent implements OnInit {
title = 'Wells';
wells: User[];
errorMessage: string;
constructor(private userService:UserService) {
this.wells = [];
}
ngOnInit() {
let self = this;
self.userService.getWells().subscribe(response => this.wells = response, error => this.errorMessage = < any > error);
}
}
Service:
import { Injectable } from '#angular/core';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable,Subject } from 'rxjs/Rx';
import 'rxjs/add/operator/toPromise';
import { User } from '../user/user';
import 'rxjs/Rx';
#Injectable()
export class UserService {
//private jsonFileURL: string='/assets/wells.json';
constructor(private http:Http) { }
getWells(): Observable < User[] > {
return this.http.get('http://localhost:8080/RESTfulExample/rest/auth/testuser1/pass',{headers:this.getHeaders()}).map((response: Response) => {
return <User[] > response.json();
}).catch(this.handleError);
}
//
private handleError(errorResponse: Response) {
console.log(errorResponse.statusText);
return Observable.throw(errorResponse.json().error || "Server error");
}
private getHeaders(){
// I included these headers because otherwise FireFox
// will request text/html instead of application/json
let headers = new Headers();
headers.append('Accept', 'application/json');
return headers;
}
}
ERROR Error: InvalidPipeArgument: '' for pipe 'AsyncPipe', i think you must check are you already include Asynce Pipe into the app.module.ts???. because this error is notice they don't have them.And this ERROR TypeError: Cannot read property 'dispose' of null at , is log after they can't run the 'AsyncPipe'. Hope this can help you fixed
asycnPipe is only deal with null, EventEmitter, promise and Observable, the wells is an object(JSON object).
enter link description here