user786
user786

Reputation: 4364

Angular @Input() not binding and not working in Angular 7

I have a master template with a component like this:

   <h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes"
    [class.selected]="hero === selectedHero"
    (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

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

The Master component is like this:

import { Component, OnInit } from '@angular/core';

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

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {

  public selectedHero: Hero;

  heroes: Hero[];

  constructor(private heroService: HeroService) { }

  ngOnInit() {
    this.getHeroes();
  }

  onSelect(hero: Hero): void {

    this.selectedHero = hero;
  }

  getHeroes(): void {
    this.heroService.getHeroes()
        .subscribe(heroes => this.heroes = heroes);
  }
}

The Master template is getting data from a service.

On clicking the master's element in list the Child details are displayed.

Using this in master:

 <li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">

and binding in to

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

But I am getting this error in the console.

ERROR TypeError: Cannot read property 'name' of undefined at HeroDetailComponent.push../src/app/hero-detail/hero-detail.component.ts.HeroDetailComponent.ngOnInit (hero-detail.component.ts:19) at checkAndUpdateDirectiveInline (core.js:22099) at checkAndUpdateNodeInline (core.js:23363) at checkAndUpdateNode (core.js:23325) at debugCheckAndUpdateNode (core.js:23959) at debugCheckDirectivesFn (core.js:23919) at Object.eval [as updateDirectives] (HeroesComponent.html:10) at Object.debugUpdateDirectives [as updateDirectives] (core.js:23911) at checkAndUpdateView (core.js:23307) at callViewAction (core.js:23548)

My child component is like this:

import { Component, OnInit, Input } from '@angular/core';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-hero-detail',
  templateUrl: './hero-detail.component.html',
  styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {

  @Input() hero: Hero;

  heroes: Hero[];

  constructor(private heroService: HeroService) {  }
  i: string;
  ngOnInit() {
    this.i = this.hero.name

    this.getHeroes();

  }
  getHeroes(): void {

    this.heroService.getHeroes(this.i)
      .subscribe(heroes => this.heroes = heroes);
  }

}

Please Note: I am using the following to bind:

@Input() hero: Hero; // in child component to parent template 

Upvotes: 1

Views: 2433

Answers (2)

Sachin Gupta
Sachin Gupta

Reputation: 5301

onInit, the hero may not be defined, its getting populated after the component has been initialized. You can try using

@Input() set hero (value) {
   if(value) {
      this.i = this.hero.name;
   }
}

Upvotes: 0

Sachila Ranawaka
Sachila Ranawaka

Reputation: 41377

use the ngOnChanges to check whether the input value is set

  ngOnChanges() {
    if(!this.hero) return null;
    this.i = this.hero.name

    this.getHeroes();

  }

Upvotes: 3

Related Questions