Angular2 *ngFor: "Cannot read property '0' of undefined"
Solution 1
I figured out the problem. I got this error because I'm fetching data asynchronously and when Angular tries to resolve bindings the first time data is still null therefore heroes[0]
fails.
So I solved the problem initializing heroes
array and using the "Elvis operator":
heroes: Hero[];
instead of heroes: Hero[] = [];
in the component.
heroes[0]?.places
instead of heroes[0].places
in the html template.
Solution 2
I guess what you want is
*ngFor="let p of heroes?.data"
because heroes
seems to be an object, and ngFor
can only iterate array.
The level
property also is in an array item.
Solution 3
Alternative to @Gunter Zochbauer's solution, you can declare heroes
as Array property of suitable type. If you have any class with all attributes of heroes
you declare heroes
property as:
heroes:Array<Heroes> //Assuming class name is Heroes
And initialize it in constructor as follows:
constructor(){
...
this.heroes=new Array<Heroes>();
}
And in your ngFor loop simply access class attributes as follows:
<option *ngFor="let p of heroes" [value]="p.place">{{p.place}}</option>
Hope it helps.
smartmouse
Considerable experience in web applications development, both as front-end developer and as CMS webmaster. Bitcoin and blockchain enthusiast as writer, speaker and developer of personal projects. An effective communicator with good leadership and analytical skills. Seeking new challenges and responsibilities to progress career. Spare time is for reading news, traveling and working on new ideas...
Updated on June 13, 2022Comments
-
smartmouse almost 2 years
I trying to get data from a JSON file to build a form.
Here is a portion of my template:
<div class="form-group"> <label for="power">Power</label> <select class="form-control" id="power" required> <option *ngFor="let p of heroes" [value]="p.level">{{p.level}}</option> </select> </div>
Here is part of the remote JSON file:
{ "data": [ { "level": "newbie", "places": [ { "place": "earth", "categories": [ { "category": "human", "values": [ ...
It works with no problem and i get
newbie
and other choices in theselect
menu. But i want to loop on places, so i edit the html template in this way:<div class="form-group"> <label for="power">Power</label> <select class="form-control" id="power" required> <option *ngFor="let p of heroes[0].places" [value]="p.place">{{p.place}}</option> </select> </div>
Here is the service that i use to grab data from JSON file:
@Injectable() export class HeroService { private url = 'app/mockups/heroes.json'; constructor(private http: Http) { } getHeroes(): Promise<Hero[]> { return this.http.get(this.url) .toPromise() .then(response => response.json().data as Hero[]) .catch(); } }
and here is the
hero.component
:export class HeroComponent implements OnInit { heroes: Hero[]; constructor(private heroService: HeroService) { } ngOnInit():void { this.getHeroes(); } getHeroes(): void { this.heroService.getHeroes().then(heroes => this.heroes = heroes); }
But i get "Cannot read property '0' of undefined" error.
Why?
-
smartmouse over 7 yearsYes, that
heroes
in the html template loops ondata
array. Now i want to loop ondata[0].places
array, where[0]
is the first object ofdata
array. -
Günter Zöchbauer over 7 yearsThat wasn't obvious from your question. I guess the error is caused by the code that assigns the json to
heroes
. -
Günter Zöchbauer over 7 yearsAccording to your update "Yes, that heroes in the html template loops on data array. " doesn't seem to be true. Did you try the code in my answer?
-
smartmouse over 7 yearsYes, i loop on
data
array because i can see items in the output. I get it from service (.then(response => response.json().data as Hero[])
). For this reason you code doesn't work. -
Günter Zöchbauer over 7 yearsThen the JSON you posed in the question is not exactly what you assign to
heroes
-
Günter Zöchbauer over 7 yearsHave you tried
[value]="p?.place"
instead of[value]="p.place"
? -
Varun Sharma over 6 yearsCould you see this link stackoverflow.com/questions/45906983/…
-
P. Nabin over 6 years@smartmouse heroes: Hero[]; instead of heroes: Hero[]; in the component. same value instead of same value, I am confused.
-
Liam about 5 yearsIsn't this exactly what Gunter said?