You need to implement a custom pipe to do this. ngFor only supports array and not object.
This pipe will look like that:
@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]});
}
return keys;
}
}
and use it like that:
<span *ngFor="#entry of content | keys">
Key: {{entry.key}}, value: {{entry.value}}
</span>
See this question for more details:
- access key and value of object using *ngFor
You need to implement a custom pipe to do this. ngFor only supports array and not object.
This pipe will look like that:
@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]});
}
return keys;
}
}
and use it like that:
<span *ngFor="#entry of content | keys">
Key: {{entry.key}}, value: {{entry.value}}
</span>
See this question for more details:
- access key and value of object using *ngFor
You can put the keys in an array and ng-repeat the keys.
export class IterateOverObject {
public arrayOfKeys;
@Input heros;
constructor() {
this.arrayOfKeys = Object.keys(this.heros);
}
}
<li *ngFor="#key of arrayOfKeys">
<span class="badge">{{key}}</span> {{heros[key].name}}
</li>
This looks simple to me.. More info is here
Loop through array of JSON object with *ngFor (Angular 4) - Stack Overflow
ngFor with JSON object - Angular 2 ngmodel perspective
How to display json object using *ngFor
You might also try out the new (alpha!) angularFire2 lib we're working on: https://github.com/angular/angularfire2, which uses Observables and thus plugs into the async pipe
More on reddit.comHow to use *ngFor on a JSON data in Angular? - Stack Overflow
For Angular 6.1+ , you can use default pipe keyvalue ( Do review also ) :
<ul>
<li *ngFor="let recipient of map | keyvalue">
{{recipient.key}} --> {{recipient.value}}
</li>
</ul>
WORKING DEMO
Previously : As you are saying :
Angular2 - *ngFor / loop through json object with array , this couldn't help you
You dont have any need of that, coz your code works fine , please check
WORKING DEMO
Your code (the part you shown) works fine (see the plunker linked below).
As the only thing not shown in your question is the way you assign your Javascript Object to the variable persons, I urge you to show you more code / search the issue there.
https://plnkr.co/edit/rj4K2sKHTHsVtdt4OWfC?p=preview
@Component({
selector: 'my-app',
template: `
<div>
<div *ngFor="let person of persons">
<p>{{person.name}}</p> <!-- this works fine-->
<p *ngFor="let color of person.colors"> <!--I want to list the colors of the person here-->
{{color.name}}
</p>
</div>
</div>
`,
})
export class App {
name:string;
constructor() {
}
persons = [
{
"name": "Mike",
"colors": [
{"name": "blue"},
{"name": "white"}
]
},
{
"name": "Phoebe",
"colors": [
{"name": "red"},
{"name": "yellow"}
]
}
];
}
Since your object has same key name every time while pushing the object will get updated with new value so how have do like this
this.record.push(Object.assign({}, username));
Read about Object.assign() from here https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
You have understood correctly that the problem is caused by the objects having same reference. As you are trying to store user details in a simple object you can easily clone the object by changing
this.record.push(username);
TO
this.record.push(_.clone(username));
The _.clone is a lodash function which will pass a new object instead of a reference.
You can also try a quick fix ( highly discouraged due to performance reasons );
this.record.push(JSON.parse(JSON.stringify(username)));
I'm following the tutorial from angular.io, and my data is coming from firebase.
http://stackoverflow.com/questions/35647365/how-to-display-json-object-using-ngfor
You might also try out the new (alpha!) angularFire2 lib we're working on: https://github.com/angular/angularfire2, which uses Observables and thus plugs into the async pipe
Instantly solved by Thierry Templier. See answer in stackoverflow. I am hoping for a simpler solution as Angular2 continues to progress.
Your component code needs refactoring. Here's how you can refactor it:
// First
import 'rxjs/add/operator/map';
// Then
ngOnInit() {
this.invoiceService.getInvoices().snapshotChanges()
.map(data => data.map(datum => datum.payload.toJSON()))
.map(data => {
return data.map(datum => {
let purchases = [];
for (let key in datum.purchases) {
purchases.push(datum.purchases[key]);
}
datum.purchases = purchases;
return datum;
});
})
.subscribe(data => this.invoiceList = data);
}
Also, since doing something along the lines of Object.0 will throw an error, you should be using the Array member access pattern. Your template will have something like:
<tr *ngFor="let invoice of invoiceList">
<td>{{invoice.customer.name}} {{invoice.customer.lastname}}</td>
<td>{{invoice.totalPrice}}</td>
<td>{{invoice.uid}}</td>
<td>{{invoice.createdAt}}</td>
<td>
<li class="list-group-item" *ngFor="let purchase of invoice.purchases">
{{purchase.product.name}}
</li>
</td>
<td>
<a class="btn btn-danger text-white" (click)="onDelete(invoice.$key)">
<i class="fas fa-trash-alt"></i>
</a>
</td>
</tr>
Here's the Updated StackBlitz.
Have Modified your code little bit.
<tr *ngFor="let invoice of invoiceList">
<td>{{invoice.customer.name}} {{invoice.customer.lastname}}</td>
<td>{{invoice.totalPrice}}</td>
<td>{{invoice.purchases["0"].product.name}}</td> //Changes are here
If key of an Object is a number, you have to access it like [0] or ["0"]
Hope That Helped!!
[ { "projectID":"1", "projectname":"project testing", "projectdescription":"
project description proketc description</p>",
"projectimage":"[{"projectimage":"1511182675-0-three13.png"}, {"projectimage":"1511182675-1-two2.png"}]" }, { "projectID":"2", "projectname":"roject settingp", "projectdescription":"
roject setting
", "projectimage":"[{"projectimage":"1511188378-0-three14.png"}, {"projectimage":"1511188378-1-two3.png"}]" }]
I am using angular4 . i want to show above json using ngFor. I used first ngFor *ngFor="let project of projectdata" I tried second ngFor like *ngFor="let projectim of project.projectimage" *ngFor="let projectim of project['projectimage']"
Above is my code I try to print using ngFor. The first ngFor working properly. But the second ngFor shows below error:
Cannot find a differ supporting object '[{"projectimage":"1511188378-0-three14.png"},{"projectimage":"1511188378-1-two3.png"}]' of type 'string'. NgFor only supports binding to Iterables such as Arrays.
projectImage isn't a json - it's a string. You have some extra quotations in there. Try putting it into https://jsonlint.com/
<div *ngFor="let project of projects">
{{project.projectID}}
<div class="card-container">
<div *ngFor="let image of project.projectimage">
{{image.projectimage}}
</div>
</div>
</div>
You have gotten some good answers here, but all are manipulating your response and changing the build of it, instead of treating it as is. There is some other data in your response and want to retain the data, so here's a solution using Pipe instead.
You seem to have two objects in your array, but only one contains routes. Will this always be the case? If not, you might want to iterate the response and show all routes (if exists) for all objects, so I'd iterate the array first, and then iterate the routes:
<!-- Iterate array -->
<div *ngFor="let obj of jsonData">
<!-- iterate routes for each object using pipe -->
<div *ngFor="let route of obj.routes | keys">
{{route.toCity}}
</div>
</div>
And then the keys pipe:
@Pipe({ name: 'keys', pure: false })
export class KeysPipe implements PipeTransform {
transform(value: any, args?: any[]): any[] {
// check if "routes" exists
if(value) {
// create instance vars to store keys and final output
let keyArr: any[] = Object.keys(value),
dataArr = [];
// loop through the object,
// pushing values to the return array
keyArr.forEach((key: any) => {
dataArr.push(value[key]);
});
// return the resulting array
return dataArr;
}
}
}
This way you have not manipulated your response, and you have access to all other data that is coming with the response.
Demo
You will want to convert your object to an iterable array.
this.http.get('data.json')
.subscribe((res) => {
let keyArr: any[] = Object.keys(res.json()[0].routes);
keyArr.forEach((key: any) => {
this.data.push(res.json()[0].routes[key]);
});
});
Here's a Plunker
Hi,
I have this code below, which correctly deserializes json to an array of my type, but for some reason ngFor thinks it's not in an array and i get a run time error in the console. Project builds fine.
I'm at a loss for why this is happening.
model
export class Month {
date: string = ""
metrics: Metrics = new Metrics()
}
export class Metrics {
wins: number = 0
losses: number = 0
draws: number = 0
averageGameTime: string = ""
highestRating: number = 0
lowestRating: number = 0
}service
getMonthlyTest() : Month[] {
var json = JSON.stringify(testMonthlyjson);
var response = JSON.parse(json) as Month[];
return response;
}code snips from component
monthlyStats: Month[] = [];
this.service.getMonthlyStats(this.username).subscribe({
next: (data: Month[]) => {
console.log("next");
console.log(data);
this.monthlyStats = data;
},
error: (error: any) => {
console.log("error");
},
complete: () => {
console.log("comp");
}
});
}html
<div *ngFor="let month of monthlyStats;index as i;">
<h3>{{month.date}}</h3>
<h1>{{month.metrics.wins}}</h1>
<h1>{{month.metrics.losses}}</h1>
<h1>{{month.metrics.draws}}</h1>
<h1>{{month.metrics.averageGameTime}}</h1>
<h1>{{month.metrics.lowestRating}}</h1>
<h1>{{month.metrics.highestRating}}</h1>
</div>ngFor iterates over tables, not objects. The error tells you so.
Your JSON is an object (it starts with {, not with [).
If you want to iterate over it, you either have to change it to an array, or you have to iterate on the keys. To do that :
this.keys = Object.keys(data);
In your HTML :
<mat-list-item *ngFor="let key of keys">
And you will acces your data with
{{ temps[key] }}
ngOnInit(): void {
this.http.get('assets/tempdata.json').subscribe(data => {
//console.log(data);
this.temps = data.temperature;
});
}
here the input json is nested object and your list lies in temperature property.. so change the code as above.