親から子にイベントを発行するにはどうすればよいですか?


111

現在Angular 2を使用しています。通常は @Output() addTab = new EventEmitter<any>();addTab.emit()親コンポーネントにイベントを発行します。

親から子に、私たちが副チェルシーを行う方法はありますか?


2
子コンポーネントへの入力として渡された式の値を変更するだけで、子コンポーネントはそれを取得します(ngOnChangesによって通知されます)。Observableを持つ共有サービスを使用してイベントを発行することもできます。
JBニゼット2017年

回答:


192

RxJを使用するSubjectと、親コンポーネントでを宣言しObservableて子コンポーネントに渡すことができます。子コンポーネントはこれをサブスクライブするだけですObservable

親コンポーネント

eventsSubject: Subject<void> = new Subject<void>();

emitEventToChild() {
  this.eventsSubject.next();
}

親HTML

<child [events]="eventsSubject.asObservable()"> </child>    

子コンポーネント

private eventsSubscription: Subscription;

@Input() events: Observable<void>;

ngOnInit(){
  this.eventsSubscription = this.events.subscribe(() => doSomething());
}

ngOnDestroy() {
  this.eventsSubscription.unsubscribe();
}

13
また、このアプローチを使用して、イベントとともにデータを渡すことができます。同様this.eventsSubject.next({data});に、親this.events.subscribe(({data}) => doSomething(data));で、次に子で。
ビンス、

2
このすばらしい回答を編集して、サブスクリプションを解除しました。+1
Umar Farooq Khawaja

1
おそらくここで初心者の質問:なぜeventsSubjectサブジェクトとしてサブスクライブするのではなく、オブザーバブルに変換するのですか?
ジャスティンモーガン

11
eventsSubjectをObservableに変換すると、子コンポーネントがnext()を呼び出せなくなります。
BlueNC、2018

2
このソリューションのおかげで、ITは機能しますが、コンソールでエラーが発生します: "core.js:6185 ERROR TypeError:Cannot read property 'subscribe' of undefined"エラーはngOnInitのevents.subscribe()を指しています子コンポーネントの: "this.eventsSubscription = this.events.subscribe(()=> doSomething());"次のバージョンを使用しています: "@ angular / cli": "〜9.1.0"と "rxjs" :「〜6.5.4」
エドゥアルド

72

私の知る限り、これを行うには2つの標準的な方法があります。

1. @入力

親のデータが変更されるたびに、子はngOnChangesメソッドでこれについて通知されます。子供はそれに行動することができます。これは子供と対話する標準的な方法です。

Parent-Component
public inputToChild: Object;

Parent-HTML
<child [data]="inputToChild"> </child>       

Child-Component: @Input() data;

ngOnChanges(changes: { [property: string]: SimpleChange }){
   // Extract changes to the input property by its name
   let change: SimpleChange = changes['data']; 
// Whenever the data in the parent changes, this method gets triggered. You 
// can act on the changes here. You will have both the previous value and the 
// current value here.
}
  1. シェアードサービスのコンセプト

サービスを作成し、共有サービスでオブザーバブルを使用します。子供はそれをサブスクライブし、変更があるたびに子供に通知されます。これも人気のある方法です。入力として渡すデータ以外のものを送信したい場合、これを使用できます。

SharedService
subject: Subject<Object>;

Parent-Component
constructor(sharedService: SharedService)
this.sharedService.subject.next(data);

Child-Component
constructor(sharedService: SharedService)
this.sharedService.subject.subscribe((data)=>{

// Whenever the parent emits using the next method, you can receive the data 
in here and act on it.})

私は最初の方法を試しましたが、ある時点まで問題なく機能し、その後、値が変更されましたというエラーメッセージが表示されました。これ以外の説明はありませんでした。
コード1

2
ExpressionChangedAfterItHasBeenCheckedErrorを意味するとすれば、このエラーはプロダクションモードではスローされません。
user1337

<child [data]="inputToChild"> </child>おそらく<child [data]="(inputToChild)"> </child>変更を取得することになるはずです
pmc

28

親コンポーネントでは、@ ViewChild()を使用して子コンポーネントのメソッド/変数にアクセスできます。

@Component({
  selector: 'app-number-parent',
  templateUrl: './number-parent.component.html'
})
export class NumberParentComponent {
    @ViewChild(NumberComponent)
    private numberComponent: NumberComponent;
    increase() {
       this.numberComponent.increaseByOne();
    }
    decrease() {
       this.numberComponent.decreaseByOne();
    }
} 

更新:

Angular 8以降-

@ViewChild(NumberComponent, { static: false })

4
これは、オブザーバブルを使用するよりもきれいに見えます。欠点は、子が表示されている必要があることです。たとえば、子にルーティングが読み込まれている場合、これは失敗しnumberComponentますundefined
Agam氏シャイ

1
これは良い習慣ですか?オブザーバブルよりもクリーンであるという事実には同意しますが、親の子の変数を操作することには疑問があります。とにかく、それは私のニーズにとてもうまくいきました、ありがとう!
Takatalvi

1
これは良いヒントです。@ViewChildがAngular 8で変更されたようです。少なくとも、ViewChildのオプションを指定する必要がありました。私はこれを私の場合に使用しました:@ViewChild(Other、{static:false})private otherComponent:Other;
Tore Aurstad

8

子コンポーネントで@Input()デコレーターを使用して、親がこの入力にバインドできるようにします。

子コンポーネントでは、それをそのまま宣言します。

@Input() myInputName: myType

プロパティを親から子にバインドするには、バインディングブラケットとそれらの間の入力名をテンプレートに追加する必要があります。

例:

<my-child-component [myChildInputName]="myParentVar"></my-child-component>

ただし、オブジェクトは参照として渡されるため、オブジェクトが子で更新されると、親の変数も更新されることに注意してください。これにより、望ましくない動作が発生する可能性があります。プライマリタイプでは、値がコピーされます。

これをさらに読むには:

ドキュメント:https : //angular.io/docs/ts/latest/cookbook/component-communication.html


1

親内では、@ ViewChildを使用して子を参照できます。必要なとき(つまり、イベントが発生するとき)は、@ ViewChild参照を使用して、親から子のメソッドを実行できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.