2016-05-15 49 views
0

我想要做一個簡單的導入,但我得到一個巨大的stack trace問題。無法讀取未定義的Angular 2的屬性

我已經嘗試過尋找與此相關的問題,但對於我來說,堆棧跟蹤不提供太多信息。

編輯:我試圖設置它不從Firebase中獲取的變量,它工作正常。我想現在的問題是,如何從Firebase處理這些信息,以便在準備就緒時加載它。

以下是相關文件:

main.ts:

import { bootstrap } from '@angular/platform-browser-dynamic'; 
import {AppComponent} from './app.component'; 
import { HTTP_PROVIDERS } from '@angular/http'; 

bootstrap(AppComponent, [HTTP_PROVIDERS]); 

player.services.ts:

import { Injectable } from '@angular/core'; 
import {Player} from "../classes/player"; 


@Injectable() 
export class PlayerService { 

    player: Player; 

    getPlayer() 
    { 
     return Promise.resolve(this.player); 
    } 

    createPlayer(uid: string, name: string, firebaseRef: Firebase) 
    { 
     this.player = { 
      'uid': uid, 
      'name': name, 
      'level': 1, 
      'maxHealth': 100, 
      'health': 100, 
      'maxEnergy': 50, 
      'energy': 50, 
      'fun': 1, 
      'skill': 1, 
      'knowledge': 1 
     } 

     firebaseRef.child('players').child(uid).set(this.player); 
    } 

    setPlayer(player: Player) 
    { 
     this.player = player; 
    } 
} 

app.component.ts

import { Component, OnInit } from '@angular/core' 
import { PlayerDetailComponent } from './components/player-detail.component'; 
import {PlayerService} from "./services/player.service"; 
import {FirebaseEventPipe} from "./firebasepipe"; 
import {Player} from "./classes/player"; 

@Component({ 
    selector: "my-app", 
    templateUrl: 'app/views/app.component.html', 
    directives: [PlayerDetailComponent], 
    providers: [PlayerService], 
    pipes: [FirebaseEventPipe] 
}) 

export class AppComponent implements OnInit{ 
    title = "title"; 

    authData: any; 

    private firebaseUrl: string; 
    private firebaseRef: Firebase; 

    private loggedIn = false; 
    player: Player; 

    constructor(private playerService: PlayerService) { 
     this.firebaseUrl = "https://!.firebaseio.com/"; 
     this.firebaseRef = new Firebase(this.firebaseUrl); 
     this.firebaseRef.onAuth((user) => { 
      if (user) { 
       this.authData = user; 
       this.loggedIn = true; 
      } 
     }); 
    } 

    getPlayer() { 
     this.firebaseRef.once("value", (dataSnapshot) => { 
      if (dataSnapshot.child('players').child(this.authData.uid).exists()) { 
       this.firebaseRef.child('players').child(this.authData.uid).once("value", (data) => { 
        this.player = data.val(); 
        this.playerService.setPlayer(this.player); 
        console.log(this.player); 
       }); 
      } else { 
       this.playerService.createPlayer(this.authData.uid, this.getName(this.authData), this.firebaseRef); 
       this.playerService.getPlayer().then(player => this.player); 
       console.log(this.player); 
      } 

     }); 




    } 

    ngOnInit() { 
     this.getPlayer(); 
    } 

    authWithGithub() { 
     this.firebaseRef.authWithOAuthPopup("github", (error) => 
     { 
      if (error) { 
       console.log(error); 
      } 
     }); 
    } 

    authWithGoogle() { 
     this.firebaseRef.authWithOAuthPopup("google",(error) => 
     { 
      if (error) { 
       console.log(error); 
      } 
     }); 

    } 

    getName(authData: any) { 
     switch (authData.provider) { 
      case 'github': 
       return authData.github.displayName; 
      case 'google': 
       return authData.google.displayName; 
     } 
    } 
} 

player-detail.component.ts

import { Component, Input, OnInit } from '@angular/core'; 
import { Player } from '../classes/player'; 


@Component({ 
    selector: "player-details", 
    templateUrl: "app/views/player-detail.component.html", 
    styleUrls: ['app/style/player-detail.component.css'], 
}) 

export class PlayerDetailComponent implements OnInit{ 
    @Input() player: Player; 

    ngOnInit() { console.log(this.player)} 
} 

app.component.html

<nav class="navbar navbar-default"> 
    <div class="container"> 
     <ul class="nav navbar-nav"> 
      <li class="navbar-link"><a href="#">Home</a></li> 
     </ul> 
    </div> 
</nav> 

<div class="jumbotron" [hidden]="loggedIn"> 
    <div class="container"> 
     <h1>Angular Attack Project</h1> 
     <p>This is a project for the <a href="https://www.angularattack.com/">Angular Attack 2016</a> hackathon. This is a small project where set goals 
      in order to gain experience as a player and person. In order to begin, please register with on of the following services</p> 
     <button class="btn btn-social btn-github" (click)="authWithGithub()"><span class="fa fa-github"></span>Sign Up With Github </button> 
     <button class="btn btn-social btn-google" (click)="authWithGoogle()"><span class="fa fa-google"></span>Sign Up With Github </button> 
    </div> 
</div> 


<player-details [player]="player" [hidden]="!loggedIn"></player-details> 

玩家detail.component.html

<div id="player" class="panel panel-default"> 
    <div id="player-stats" class="panel-body"> 
     <img id="player-image" class="img-responsive" src="../app/assets/images/boy.png"/> 
     <div class="health-bars"> 
      <div class="health-bar">HEALTH:<br/><progress value="{{ player.health }}" max="{{ player.maxHealth }}"></progress></div> 
      <div class="energy-bar">ENERGY:<br/><progress value="{{ player.energy }}" max="{{ player.maxEnergy }}"></progress></div> 
      <div class="player-attributes"><span class="fa fa-futbol-o player-attr fun">: {{ player.fun }} </span><span class="fa fa-cubes player-attr skill">: {{ player.skill }}</span> <span class="fa fa-graduation-cap player-attr knowledge">: {{ player.knowledge }}</span></div> 
     </div> 
    </div> 
</div> 
+0

堆棧跟蹤表明錯誤來自player-detail.component.html ...您可以包含該代碼嗎? – sourdoughdetzel

+0

對不起,以爲我加了。 – ReallyGoodPie

回答

0

PlayerDetailComponent被加載時,玩家變量未定義,因此沒有玩家等對象。

爲了解決這個問題,OnChanges可以實現這樣的:

import { Component, Input, OnChanges, SimpleChange } from '@angular/core'; 
import { Player } from '../classes/player'; 
import {HealthBarComponent} from "./health-bar.component"; 
import {ChecklistComponent} from "./checklist.component"; 


@Component({ 
    selector: "player-details", 
    templateUrl: "app/views/player-detail.component.html", 
    styleUrls: ['app/style/player-detail.component.css'], 
    directives: [HealthBarComponent, ChecklistComponent], 
}) 

export class PlayerDetailComponent implements OnChanges{ 

    @Input() 
    player: Player; 

    ngOnChanges(changes: {[propName: string]: SimpleChange}) { 
    } 


} 

,然後我們就可以在模板中添加*nfIf="player",以確保選手對象不加載元素之前的空白。

1

在你的服務,你不必與承諾返回。您可以在組件中使用一個getter

private player: Player; 

get CurrentPlayer() 
{ 
    return this.player; 
} 

然後:

getPlayer() { 

      this.firebaseRef.once("value", (dataSnapshot) => { 
       if (dataSnapshot.child('players').child(this.authData.uid).exists()) { 
        this.firebaseRef.child('players').child(this.authData.uid).once("value", (data) => { 
this.playerService.setPlayer(this.player);       
         console.log(this.player); 
        }); 
       } else { 
        this.playerService.createPlayer(this.authData.uid, this.getName(this.authData), this.firebaseRef); 
        console.log(this.player); 
       } 

      }); 

     ngOnInit() { 
    this.player = this.playerService.CurrentPlayer(); 
      this.getPlayer(); 
     } 

如果您設置的參考第一,它應該自動更新。您還可以在DOM中拋出一個* ngIf播放器細節組件定義,並且只有在播放器對象未定義時才顯示它。

編輯 剛纔看到有人在我之前發佈了* ngIf,所以如果這是解決方案,請標記他們的。

+0

根據我的理解,這是非常有限的,它只是一種處理異步調用的方式。這在我的應用程序中絕對不需要,我已經將它改回到'this.player = this.playerService.getPlayer()',並且錯誤仍然存​​在。 – ReallyGoodPie

+0

我建議你做的是這個...... this.playerService.getPlayer()。然後((player)=> {this.player = player;});' – sourdoughdetzel

+0

這樣做更有意義,但我認爲我使用的方法起作用,因爲我仍然在console.log中獲取值。實施你的方法似乎也不能解決問題。 – ReallyGoodPie

相關問題