@Input property is undefined in Angular 2's onInit

Trying to get the component's @Input value in constructor or ngOnInit. But it is coming as undefined all the time.

I updated the hero plunker with console.log to show the issue (beta angular). http://plnkr.co/edit/dseNM7OTFi1VNG2Z4Oj5?p=preview

export class HeroDetailComponent implements OnInit {
constructor(){
console.log('hero', this.hero)
}
public hero: Hero;
  

ngOnInit() {
console.log('hero', this.hero)
}
}

What am I doing wrong here?

70083 次浏览

The reason you're getting undefined in ngOnInit is because at the point where the component is initialised you haven't actually passed in a Hero object

<my-hero-detail [hero]="selectedHero"></my-hero-detail>

At this point selectedHero has no value in your AppComponent and doesn't until the click event on the list calls the onSelect method

Edit: Sorry realised I didn't actually offer a fix. If you add an ngIf to my-hero-detail

<my-hero-detail *ngIf="selectedHero" [hero]="selectedHero"></my-hero-detail>

you should this will delay the initialisation of the my-hero-detail component and you should see the console output. This wont however output again when the selected hero changes.

This is because the heroes are loaded asynchronously, so when the view renders initially, the selected hero is undefined. But then after a selection is made, the hero is passed into the details view with a defined value.

You are basically just seeing the onInit call based on the original value (undefined).

If you want something similar to execute after each selection, you can modify it like this:

export class HeroDetailComponent implements AfterViewChecked {
constructor(){
console.log('hero', this.hero)
}
public hero: Hero;


ngAfterViewChecked() {
console.log('hero', this.hero)
}
}

I encountered the same behavior when I've got undefined of Input property value in ngOnInit. The statement *ngIf="selectedHero" in html code was not satisfied me. Moreover, using AfterViewChecked from @THG's answer was not a good solution for me, because it calls periodically and also it causes the warning ExpressionChangedAfterItHasBeenCheckedError when I want to change some variable (I didn't want to use workaround setTimeout). This is my solution for kind of this issue:

export class MyComponent implements OnChanges {
@Input() myVariable: any;


ngOnChanges(changes: SimpleChanges) {
if (changes['myVariable']) {
let variableChange = changes['myVariable'];
//do something with variableChange.currentValue
}
}
}

I hope it helps someone later.

In the ngOninit method use,

ngOnInit() {
if(this.hero)
console.log('hero', this.hero);
}

@Barabas solution did not work in my case. I end up using this

export class HeroDetailComponent implements OnChanges {
@Input() hero: any;


ngOnChanges(changes: SimpleChanges){
if(changes.hero && changes.hero.currentValue){
let currentHero = changes.hero.currentValue;
//use currentHero
}
}
}