エラーを発生させる私のコードは、未定義のプロパティタイトルを読み取れません。
親コンポーネント
import { Child } from './child.component';
@Component({
selector: 'parent',
})
export class ParentComponet implements OnInit, AfterViewInit {
constructor(){}
@ViewChild(Child) child: Child;
ngAfterViewInit(){
console.log("check data", this.child.title)
}
}
そして子コンポーネントです。
@Component({
selector: 'child',
})
export class ChildComponet {
public title = "hi"
constructor(){}
}
routing.module.tsは
{
path: "",
component: ParentComponent,
children: [
{
path: '/child',
component: ChildComponent
}
]
}
そして、エラーは
ERROR TypeError: Cannot read property 'title' of undefined(…)
コンポーネントの作成に関連して'template'または 'templateUrl'が欠落していると思います
ParentComponent
import { ChildComponent } from './child.component'; // {ChildComponent} not {Child} as we are referencing it to the exported class of ChildComponent
@Component({
selector: 'parent',
template: `<child></child>`
})
export class ParentComponet implements OnInit, AfterViewInit {...}
ChildComponent
@Component({
selector: 'child',
template: `<h1>{{ title }}</h1>`
})
export class ChildComponent {...} // Be sure to spell it right as yours were ChildComponet - missing 'n'
[〜#〜] update [〜#〜]このスレッドに関するユーザーの説明に従って
参照用に Stackblitz Demo を追加しました(コンソールを確認してください)
親コンポーネントの下にレンダリングされたChildComponentにアクセスする場合は、<router-outlet>
これを行うには、ルーターアウトレットの(アクティブ化)サポートされるプロパティを使用します。
ルーターアウトレットは、新しいコンポーネントがインスタンス化されるたびに、アクティブ化イベントを発行します
ParentComponentのテンプレート
@Component({
selector: 'parent',
template: `<router-outlet (activate)="onActivate($event)"></router-outlet>`
})
export class ParentComponent {
onActivate(event): void {
console.log(event); // Sample Output when you visit ChildComponent url
// ChildComponent {title: "hi"}
console.log(event.title); // 'hi'
}
}
結果は、アクセスしたページによって異なります親の子の下
Child1Componentにアクセスすると、そのインスタンスを取得します
Child1Component {title: "hi"}
Child2Componentにアクセスすると、そのインスタンスを取得します
Child2Component {name: "Angular"}
これらの結果は、ParentComponentのonActivate(event)コンソールに反映され、アクセスできます
それはそれが機能するはずの方法ではありません。 ChildComponent
でのみParentComponent
を取得できます[〜#〜]のみ[〜#〜]ParentComponent
テンプレートに<app-child></app-child>
タグがある場合。
このようなもの:
...
<app-child></app-child>
...
ただし、子ルーティングを使用しているため、ChildComponent
はParentComponent
のrouter-outlet
にロードされるため、ViewChild
を使用してアクセスすることはできません。
PS:ngAfterViewInit
はインスタンス化しても安全であると見なすことができるため、ViewChild
内でのみアクセスできます。ビューが読み込まれた後:
import { Component, OnInit, ViewChild } from '@angular/core';
import { ChildComponent } from '../child/child.component';
...
@Component({...})
export class ParentComponent implements OnInit {
@ViewChild(ChildComponent) childComponent: ChildComponent;
...
ngAfterViewInit() {
console.log(this.childComponent);
}
}
これは、両方のケースでのシナリオを示す、refの Working Sample StackBlitz です。
PS:ルーティングでChildComponent
のParentComponent
プロパティを取得するには、ルーティングを使用するか、 SharedService
または、ルートのChildPropertyをQueryParamとして渡し、ActivatedRoute
を使用してParentComponentでそれを読み取る必要があります。
これはあまり意味がありませんが、ChildComponent
には、title
プロパティをqueryParam
として渡して、ユーザーをChildComponentにルーティングするリンクを含めることができます。 。このようなもの:
<a
[routerLink]="['/child']"
[queryParams]="{title: title}">
Go To Child Route With Query Params
</a>
そして、あなたのParentComponent
では、次のようにActivatedRoute
を使用してそれにアクセスできます。
...
import { ActivatedRoute } from '@angular/router';
...
@Component({...})
export class ParentComponent implements OnInit {
...
constructor(
private route: ActivatedRoute,
...
) { }
ngOnInit() {
this.route.queryParams.subscribe(queryParams => {
console.log('queryParams[`title`]', queryParams['title']);
});
...
}
...
}
SharedService
を使用するSharedService
を作成し、private
BehaviorSubject
を使用してObservable
メソッドを呼び出すことで、asObservable
として公開されます。その値は、更新されたsetChildProperty
値でnext
メソッドを本質的に呼び出すmethod(childProperty
)を公開することによって設定できます。
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class SharedService {
private childProperty: BehaviorSubject<string> = new BehaviorSubject<string>(null);
childProperty$: Observable<string> = this.childProperty.asObservable();
constructor() { }
setChildProperty(childProperty) {
this.childProperty.next(childProperty);
}
}
次に、それをParentComponent
とChildComponent
の両方に注入できます。
ChildComponent
に値を設定します。
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared.service';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
public title = "hi"
constructor(private sharedService: SharedService) { }
ngOnInit() {
this.sharedService.setChildProperty(this.title);
}
}
そして、ParentComponent
で値を取得します。
...
import { SharedService } from '../shared.service';
@Component({...})
export class ParentComponent implements OnInit {
...
constructor(
...,
private sharedService: SharedService
) { }
ngOnInit() {
...
this.sharedService.childProperty$.subscribe(
childProperty => console.log('Got the Child Property from the Shared Service as: ', childProperty)
);
}
...
}
parent.component.html
追加したテンプレート<child></child>
鬼ごっこ。