У меня есть мастер-шаблон с таким компонентом:
<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>]
Главный компонент выглядит следующим образом:
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);
}
}
Шаблон Master получает данные от службы.
При нажатии на основной элемент в списке отображаются дочерние детали.
Используя это в мастере:
<li *ngFor = "let hero of heroes"
[class.selected] = "hero === selectedHero"
(click) = "onSelect(hero)">
и привязка к
<app-hero-detail [hero] = "selectedHero"></app-hero-detail>]
Но я получаю эту ошибку в консоли.
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)
Мой дочерний компонент выглядит так:
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);
}
}
Обратите внимание: я использую следующее для привязки:
@Input() hero: Hero; // in child component to parent template
используйте ngOnChanges, чтобы проверить, установлено ли входное значение
ngOnChanges() {
if (!this.hero) return null;
this.i = this.hero.name
this.getHeroes();
}
onInit, hero
может быть не определен, он заполняется после инициализации компонента. Вы можете попробовать использовать
@Input() set hero (value) {
if (value) {
this.i = this.hero.name;
}
}
Есть много подобных вопросов к этому ОП. Но на самом деле это решает, как мы можем получить данные из API, переданные от родителя к дочернему свойству @input. Если вы хотите консольировать данные, они будут неопределенными в ngOnInit. Это метод (жизненный цикл), где нам нужно это сделать - спасибо! Идеальный ответ.