2017-05-15 30 views
0

因此,我浏览了Angular网站上的文档,并构建了基本的“英雄”应用程序。如何访问此变量? this.hero

我一直在尝试访问输入变量的英雄,因为我有一个特定的变量,我想输出但是我收到错误。

Error: Uncaught (in promise): TypeError: this.hero is undefined 

该调用工作在任何其他方法,例如是按钮在使用过程中调用的方法,但是一旦我尝试调用它ngOnInit()崩溃,并给了我这个错误。

这里是我的代码:

this.route.params.switchMap((params: Params) => this.heroService.getHero(+params['id'])).subscribe(hero => this.hero = hero); 
console.log(this.hero.background); 

其中背景是英雄的属性。

我不需要特定的代码 - 这只是本教程未涉及的内容,我想要一些指导。

我花了很多小时寻找,但我总是最终失败 - 现在我撕下我所有的听到有人可以给我一些指导?

了要求代码,所以这里是

import { Component, Input, OnInit } from '@angular/core'; 
import { ActivatedRoute, Params } from '@angular/router'; 
import { Location }     from '@angular/common'; 

import { HeroService } from './hero.service'; 
import { Hero } from './hero'; 

import 'rxjs/add/operator/switchMap'; 

let body = document.getElementsByTagName('body')[0]; 
@Component({ 
    selector: 'hero-detail', 
    templateUrl: './hero-detail.component.html', 
    styleUrls: [ './hero-detail.component.css' ] 
}) 


export class HeroDetailComponent implements OnInit { 
    @Input() hero: Hero; 
    constructor(
    private heroService: HeroService, 
    private route: ActivatedRoute, 
    private location: Location 
) { } 

    oldBody:string = body.style.backgroundImage; 

    ngOnInit(): void { 
    this.route.params.switchMap((params: Params) => this.heroService.getHero(+params['id'])).subscribe(hero => this.hero = hero); 

    console.log(this.hero.background); 
    } 

    ngOnDestroy() { 
     body.style.backgroundImage = this.oldBody; 
    } 

    goBack(): void { 
    this.location.back(); 
    } 

    updateBackground(): void { 
    body.style.backgroundImage = "url('"+this.hero.background+ "')"; 
    } 

    save(): void { 
    this.heroService.update(this.hero) 
    .then(() => this.goBack()); 
    } 
} 
+0

按照你的逻辑步骤一步,确保了“这个”关键词是在你认为它是上下文。 – Bindrid

+0

@Bindrid在我的变量声明中,我有'@Input()hero:Hero;'所以访问它会被“this”关键字使用吗?我的意思是我没有其他方式,我知道 - 如果我使用没有这个关键字的普通英雄,它会给我一个错误,要求我引用该实例。 – seeocon

+0

你能提供更多的代码吗? – Tamas

回答

0

问题是,在observable订阅有机会触发之前,您的console.log正在运行。在订阅回调实际运行之前,“英雄”字段将是未定义的。

你应该控制台日志移动到这样的订阅:

this.route.params.switchMap((params: Params) => 
    this.heroService.getHero(+params['id']) 
).subscribe(hero => { 
    this.hero = hero; 
    console.log(this.hero.background); 
}); 
+0

哈哈哇,这很快,感谢您的反馈。我想每个人都必须从某个地方开始。 为了更好地理解您的更改;我正在做的是严格定义变量,但** ngOnInit **实际上并没有实际初始化变量,通过创建一个块来确保变量被初始化? – seeocon

+0

使它成为一个块(添加大括号)除了可以让你编写多个语句之外不会改变任何内容。 (作为一个惯例,我总是在订阅回调中使用花括号,即使它只有一个声明,我认为它更清晰。) 无论如何,'subscribe'函数中的代码是异步运行的(getHero()完成后)。但是,在以前的console.log之前的订阅回调之外的代码会同步运行。 – dbandstra

0

你实际提供一个英雄为Input()当您使用组件?如果没有,你的代码应该只是阅读:

export class HeroDetailComponent implements OnInit { 
    public hero: Hero 
// rest of your code 
+0

我是为了这个例子,但当我开始制作我的迷你应用程序时,我停止使用它。我曾尝试将其更改为公开,但仍然无效。 :\ – seeocon

+0

当你想出一个非常简单/基本的组件时会发生什么?类似于导出类TestComponent实现OnInit {public message; ngOnInit()this.message ='hello'; }这应该只是工作。 – Tamas

0

既然你定义hero为您的组件的Input,你可以直接从您为父级设置为它象下面这样:

<hero-detail [hero]="selectedHero"></hero-detail> // here selectedHero is what you selected from ParenComponent 

,并根据您正面临的错误(this.hero is undefined),您没有执行上述操作,因此@Input() hero仍未定义,直到您从this.heroService.getHero获得数据为止。

因此,只需将console.log移动到this.heroService.getHerosubscribe即可,因为它是异步调用。