Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 : TypeError 'this.' is undefined

I wrote a function that gets and shows the "best player" from my array of objects (the player who has most likes). The function works fine and shows me what I want, but the browser shows me errors in the console, and the routing in my app is blocked (I can't 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 show me those errors :

TypeError: this.data[i] is undefined Error: Uncaught (in promise): Error: Cannot activate an already activated outlet Error: Uncaught (in promise): Error: Cannot activate an already activated outlet

when I delete whats in ngOninit() and viewDetails() function, routing starts working again and browser doesn't show me errors.

Any help please !

like image 397
Hamdi Gatri Avatar asked Aug 11 '26 19:08

Hamdi Gatri


1 Answers

As a sidenote, always when you provide a plunker, make sure it's a working one ;) When I got it working, there was only a couple of issue actually. There was nothing wrong with your routing. The first error you were getting

this.data[i] is undefined

is because of your for loop, you had marked that we should loop until i matches the length of the array (or equal). But we need to remember that the index of arrays start with 0. So the last iteration it was trying to read an index that was not present in your array. So you should add -1 to your 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 was fixed, it produces new issues. Since data is coming async, so by the time the template is rendered, your variable bestPlayer is undefined. This can be fixed with safe navigation operator, or wrapping everything inside a div with the condition that bestPlayer has values. This need to be applied to both the detail page and the dashboard. With the dashboard:

<div *ngIf="bestPlayer">
  <!-- code here -->
</div>

And in the detail page the same but using player instead, as that is the variable you are using there.

As mentioned, you can also use the safe navigation operator.

These actually cleared the second error you also had.

Here's your fixed PLUNKER.

like image 123
AT82 Avatar answered Aug 14 '26 09:08

AT82