Reputation: 23226
I am trying to iterate over an Array property of an object as below:
<p>
Editing Course : {{course?.name}}<br/>
Course Outward Par : {{course?.getOutwardPar('MEDAL')}}<br/>
Course Outward Yards : {{course?.getOutwardYards('MEDAL')}}
</p>
<div class="container">
<h1>Course Form</h1>
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
<div class="form-group">
<table>
<tr>
<td><label for="name">Name</label></td>
<td><input type="text" class="form-control" id="name" name="name" required
[(ngModel)]="course && course.name">
</td>
</tr>
<tr>
<input type="number" class="form-control" id="hole1" name="hole1" required
[(ngModel)]="course && course.holes[1].tees['MEDAL'].par">
</tr>
<!--
--- BROKEN HERE---
-->
<tr *ngFor="let hole of course?.holes">
<td>{{hole.name}}</td>
</tr>
</table>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
Everything prior to the *ngFor works as expected including the below so the property holes
of course
can surely be considered to be an array. No?
<input type="number" class="form-control" id="hole1" name="hole1" required
[(ngModel)]="course && course.holes[1].tees['MEDAL'].par">
The ngFor triggers the error:
Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
There is some dicusssion here https://github.com/angular/angular/issues/6392 on the subject. The post by robwormald suggests that the ? opertaor can be used in such cases.
Upvotes: 1
Views: 1407
Reputation: 23226
Okay it appears Angular 2 does not support using associative arrays / Dictionaries in *ngFor
e.g. JSON with the structure below.
See for example:
Iterate over TypeScript Dictionary in Angular 2
I could get this to work by simply creating a keys variable in the Component and iterating that. Other solutions propose using a Directive but that's for later.
e.g.
keys: string [];
this.keys = Object.keys(this.course.holes);
and iterating the keys
<tr *ngFor="let key of keys">
<td>{{key}}</td>
<td>{{course.holes[key].name}}</td>
<td>
<input type="number" class="form-control" id="hole{{key}}" name="holePar{{key}}"
[(ngModel)]="course && course.holes[key].tees['MEDAL'].par"/>
</td>
<td>
<input type="number" class="form-control" id="hole{{key}}" name="holeLength{{key}}"
[(ngModel)]="course && course.holes[key].tees['MEDAL'].length"/>
</td>
</tr>
Source JSON:
{
"name": "Ny Course",
"courseTeeSets": [],
"holes": {
"1": {
"id": 1,
"number": 1,
"name": "Hole Number 1",
"tees": {
"MEDAL": {
"id": 3,
"teeType": "MEDAL",
"length": 100,
"strokeIndex": 15,
"par": 8
},
"MENS": {
"id": 1,
"teeType": "MENS",
"length": 509,
"strokeIndex": 15,
"par": 5
},
"LADIES": {
"id": 2,
"teeType": "LADIES",
"length": 489,
"strokeIndex": 15,
"par": 5
}
}
},
"2": {
"id": 2,
"number": 2,
"name": "Hole Number 2",
"tees": {
"MEDAL": {
"id": 4,
"teeType": "MEDAL",
"length": 110,
"strokeIndex": 9,
"par": 8
},
"MENS": {
"id": 6,
"teeType": "MENS",
"length": 191,
"strokeIndex": 9,
"par": 4
},
"LADIES": {
"id": 5,
"teeType": "LADIES",
"length": 171,
"strokeIndex": 9,
"par": 4
}
}
}
}
}
Upvotes: 1