Angular2: TypeError 'this.' undefined
I wrote a function that gets and shows the "best player" from my array of objects (the player who likes the most). The function works fine and shows me what I want, but the browser shows me errors in the console and routing in my application is blocked (I cannot navigate between components using routes)
this is my DashboardComponent class
export class DashboardComponent implements OnInit {
bestPlayer:Player;
data:Player[]=[];
max:number =0;
constructor(private playerService : PlayerService ,private router: Router) { }
ngOnInit() {
this.playerService.getData().then(data => {
this.data = data;
for (var i = 0; i <= this.data.length; i++) {
if (this.data[i].likes>this.max) {
this.max=this.data[i].likes;
this.bestPlayer=this.data[i];
}
}
});
}
viewDetails(bestPlayer: Player):void {
this.router.navigate(['/detail',this.bestPlayer.id]);
}
}
This is my service:
import {Player} from './player';
import {PlayersData} from './muck-players';
import { Injectable } from '@angular/core';
@Injectable()
export class PlayerService {
players:any;
data:any;
Player:Player;
getData():Promise <Player[]> {
return Promise.resolve(PlayersData);
}
}
when i run the app the browser shows me these errors:
TypeError: this.data [i] is undefined Error: not visible (in a promise): Error: do not activate an already activated socket Error: not shown (in a promise): Error: do not activate an already activated socket
when I remove the functions ngOninit()
and viewDetails()
, the routing starts working again and the browser doesn't show me errors.
Any help please!
source to share
Assalamualaikum,
I have dozens of bugs fixed in Plunker and added some missing routing features. The app is working fine now, please take a look at my forked Plunker here
I fixed all the file paths and used in the forEach
method in your component like so:
ngOnInit() {
this.playerService.getData().then(data => {
data.forEach( (arrData) => {
if (arrData.likes>this.max) {
this.max=arrData.likes;
this.bestPlayer=arrData;
}
})
});
}
I really hope this helps you Hamdi and wishes you all the best for your project and if you have any questions just let me know, I will be more than happy to help
Ramadan Mubarak.
source to share
As a side-item, whenever you provide a plunker, make sure it works.) When I got it working, there were really only a couple of problems. There was nothing wrong with your routing. The first error you received
this.data [i] - undefined
due to your for loop, you noted that we must loop until i
it matches the length of the array (or equal). But we must remember that the index of arrays starts with 0
. So the last iteration was trying to read an index not present in your array. Therefore, you must add -1
to the for loop:
for (var i = 0; i <= this.data.length-1; i++)
or do
for (var i = 0; i < this.data.length; i++)
When this has been fixed, new issues arise. Since the data comes in async, so by the time the template is rendered, your variable bestPlayer
is undefined. This can be eliminated with a safe navigation statement or wrapped with a condition, which matters. This needs to be applied on both the detail page and the dashboard. Using the control panel: div
bestPlayer
<div *ngIf="bestPlayer">
<!-- code here -->
</div>
And on the detail page is the same, but using player
instead, since this is the variable you are using there.
As mentioned, you can also use Safe Navigator.
They did clean up the second error you also had.
Here is your fixed PLUNKER .
source to share
Hi there is a problem with your service,
You are trying to iterate over data that is not available,
You need to change the code, If you are using Observer as a service then put the code inside the .subscribe method,
If you are using a promise, put your looping code in the .then () method.
Try using this:
If you return a promise from this.playerService.getData()
this service
this.playerService.getData().then((data) => {
this.data = data;
for (var i = 0; i <= this.data.length; i++) {
if (this.data[i].likes>this.max) {
this.max=this.data[i].likes;
this.bestPlayer=this.data[i];
}
})
If you are returning an observable from this.playerService.getData()
this service
this.playerService.getData().subscribe((data) => {
this.data = data;
for (var i = 0; i <= this.data.length; i++) {
if (this.data[i].likes>this.max) {
this.max=this.data[i].likes;
this.bestPlayer=this.data[i];
}
})
source to share